From 5567261cb0e3635321c313df13c7a2483a0be9ef Mon Sep 17 00:00:00 2001 From: Matthieu Guillaumin Date: Tue, 26 Feb 2013 17:22:15 +0100 Subject: [PATCH 1/8] major modifications: thumbnails, bibliography, keys, list display --- bibtexbrowser.local.php | 279 +++++++++++++++++++++++++++++++++ bibtexbrowser_bibliography.php | 37 +++++ 2 files changed, 316 insertions(+) create mode 100644 bibtexbrowser.local.php create mode 100644 bibtexbrowser_bibliography.php diff --git a/bibtexbrowser.local.php b/bibtexbrowser.local.php new file mode 100644 index 0000000..d949c64 --- /dev/null +++ b/bibtexbrowser.local.php @@ -0,0 +1,279 @@ +getTitle(); + $type = $bibentry->getType(); + + // later on, all values of $entry will be joined by a comma + $entry=array(); + + + // thumbnail + if (USEBIBTHUMBNAIL && $bibentry->hasField(BIBTHUMBNAIL)) { + $thumb = '';} + else $thumb = ''; + + // title + // usually in bold: .bibtitle { font-weight:bold; } + $title = ''.$title.'
'."\n"; + if ($bibentry->hasField('url')) $title = ''.$title.''; + + + // author + if ($bibentry->hasField('author')) { + $coreInfo = $title . ''.$bibentry->getFormattedAuthorsImproved().'';} + else $coreInfo = $title; + + // core info usually contains title + author + $entry[] = $thumb.$coreInfo; + + // now the book title + $booktitle = ''; + if ($type=="inproceedings") { + $booktitle = 'In '.$bibentry->getField(BOOKTITLE); } + if ($type=="incollection") { + $booktitle = 'Chapter in '.$bibentry->getField(BOOKTITLE);} + if ($type=="inbook") { + $booktitle = 'Chapter in '.$bibentry->getField('chapter');} + if ($type=="article") { + $booktitle = 'In '.$bibentry->getField("journal");} + + //// we may add the editor names to the booktitle + $editor=''; + if ($bibentry->hasField(EDITOR)) { + $editor = $bibentry->getFormattedEditors(); + } + if ($editor!='') $booktitle .=' ('.$editor.')'; + // end editor section + + // is the booktitle available + if ($booktitle!='') { + $entry[] = '
'.$booktitle.''; + } + + + $publisher=''; + if ($type=="phdthesis") { + $publisher = 'PhD thesis, '.$bibentry->getField(SCHOOL); + } + if ($type=="mastersthesis") { + $publisher = 'Master\'s thesis, '.$bibentry->getField(SCHOOL); + } + if ($type=="bachelorsthesis") { + $publisher = 'Bachelor\'s thesis, '.$bibentry->getField(SCHOOL); + } + if ($type=="techreport") { + $publisher = 'Technical report, '.$bibentry->getField("institution"); + } + + if ($type=="misc") { + $publisher = $bibentry->getField('howpublished'); + } + + if ($bibentry->hasField("publisher")) { + $publisher = $bibentry->getField("publisher"); + } + + if ($publisher!='') $entry[] = ''.$publisher.''; + + + if ($bibentry->hasField('volume')) $entry[] = "volume ".$bibentry->getField("volume"); + + + if ($bibentry->hasField(YEAR)) $entry[] = $bibentry->getYear(); + + $result = implode(", ",$entry).'.'; + + // some comments (e.g. acceptance rate)? + if ($bibentry->hasField('comment')) { + $result .= " (".$bibentry->getField("comment").")"; + } + if ($bibentry->hasField('note')) { + $result .= " (".$bibentry->getField("note").")"; + } + + // add the Coin URL + //$result .= "\n".$bibentry->toCoins(); + $result .= "
\n"; + + // we add biburl and title to be able to retrieve this important information + // using Xpath expressions on the XHTML source + $result .= $bibentry->getBibLink(); + // returns an empty string if no pdf present + $result .= $bibentry->getLink('pdf'); + // returns an empty string if no url present + $result .= $bibentry->getLink('url'); + // returns an empty string if no slides present + $result .= $bibentry->getLink('slides'); + // returns an empty string if no poster present + $result .= $bibentry->getLink('poster'); + // Google Scholar ID. empty string if no gsid present + $result .= $bibentry->getGSLink(); + // returns an empty string if no doi present + $result .= $bibentry->getDoiLink(); + + $result .= '
'; + + return $result; +} + +/** Class to display a bibliography of a page. */ +class BibliographyDisplay { + /** the bib entries to display. */ + var $result; + + /** the content strategy (cf. pattern strategy) */ + var $contentStrategy; + + /** the query to reinject in links to different pages */ + var $filter; + + /** Creates an instance with the given entries and header. */ + function BibliographyDisplay(&$result, $filter) { + $this->result = $result; + $this->filter = $filter; + // requesting a different page of the result view? + $this->setTitle(); + $this->contentStrategy = new BibliographyContentStrategy(); + } + + /** sets the $this->title of BibtexBrowserDisplay based on the $filter */ + function setTitle() { + $this->title = query2title($this->filter); + } + + /** overrides */ + function formatedHeader() { return '
'.$this->title.' '.createRSSLink($this->filter).'
';} + + /** overrides */ + function getURL() { return '?'.createQueryString($this->filter);} + + /** overrides */ + function getRSS() { return BIBTEXBROWSER_URL.'?'.createQueryString($this->filter).'&rss';} + + /** Displays the entries preceded with the header. */ + function display() { + // print error message if no entry. + if (empty($this->result)) { + echo "No references.\n"; + return; + } + $this->contentStrategy->display($this); + echo $this->poweredby(); + if (BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT) { + $this->javascript(); + } + } + + + function poweredby() { + $poweredby = "\n".'
'; + $poweredby .= ''; + $poweredby .= 'Powered by bibtexbrowser'; + $poweredby .= '
'."\n"; + return $poweredby; + } + + /** Adds a touch of AJAX in bibtexbrowser to display bibtex entries inline. + * It uses the HIJAX design pattern: the Javascript code fetches the normal bibtex HTML page + * and extracts the bibtex. + * In other terms, URLs and content are left perfectly optimized for crawlers + * Note how beautiful is this piece of code thanks to JQuery. + */ + function javascript() { + // we use jquery with the official content delivery URLs + // Microsoft and Google also provide jquery with their content delivery networks +?> + +
    + + + +
    + result; + $refnum = count($display->result); + + foreach ($entries as $value => $bib) { + $bib->setAbbrv($value); + switch(LAYOUT) { + case 'list': $bib->toLI(); break; + case 'table': $bib->toTR(); break; + case 'deflist': $bib->toDD(); break; + } + } // end foreach + + switch(LAYOUT) { + case 'list': + ?> + + +
    + + + + diff --git a/bibtexbrowser_bibliography.php b/bibtexbrowser_bibliography.php new file mode 100644 index 0000000..8cdbc30 --- /dev/null +++ b/bibtexbrowser_bibliography.php @@ -0,0 +1,37 @@ +' . $a . '' ; +} + +// Create citations from bibtex entries. One argument per bibtex entry. +/* Example: As shown in , one can cite +*/ +function cite() { + global $citations; + $entries = func_get_args(); // list of bibtex entries + $refs = array(); // corresponding references + foreach ($entries as $entry) { + if ( array_key_exists ( $entry , $citations ) ) { + $ref = $citations[$entry] ; + } else { + $ref = count( $citations ) + 1 ; + $citations[$entry] = $ref ; + } + $refs[] = $ref; + } + sort( $refs ); + $links = array_map( 'linkify', $refs ); + echo "[" . implode(",",$links) . "]" ; +} + +function make_bibtexbrowser_bibliography() { + global $citations; + return json_encode($citations) ; +} + +?> From 74cb778193ade2eab61e409d463641040fee97d9 Mon Sep 17 00:00:00 2001 From: Matthieu Guillaumin Date: Tue, 26 Feb 2013 17:22:15 +0100 Subject: [PATCH 2/8] major modifications: thumbnails, bibliography, keys, list display --- bibtexbrowser.local.php | 279 ++++ bibtexbrowser.php | 2695 +++++++++++++++----------------- bibtexbrowser_bibliography.php | 37 + 3 files changed, 1578 insertions(+), 1433 deletions(-) create mode 100644 bibtexbrowser.local.php create mode 100644 bibtexbrowser_bibliography.php diff --git a/bibtexbrowser.local.php b/bibtexbrowser.local.php new file mode 100644 index 0000000..d949c64 --- /dev/null +++ b/bibtexbrowser.local.php @@ -0,0 +1,279 @@ +getTitle(); + $type = $bibentry->getType(); + + // later on, all values of $entry will be joined by a comma + $entry=array(); + + + // thumbnail + if (USEBIBTHUMBNAIL && $bibentry->hasField(BIBTHUMBNAIL)) { + $thumb = '';} + else $thumb = ''; + + // title + // usually in bold: .bibtitle { font-weight:bold; } + $title = ''.$title.'
    '."\n"; + if ($bibentry->hasField('url')) $title = ''.$title.''; + + + // author + if ($bibentry->hasField('author')) { + $coreInfo = $title . ''.$bibentry->getFormattedAuthorsImproved().'';} + else $coreInfo = $title; + + // core info usually contains title + author + $entry[] = $thumb.$coreInfo; + + // now the book title + $booktitle = ''; + if ($type=="inproceedings") { + $booktitle = 'In '.$bibentry->getField(BOOKTITLE); } + if ($type=="incollection") { + $booktitle = 'Chapter in '.$bibentry->getField(BOOKTITLE);} + if ($type=="inbook") { + $booktitle = 'Chapter in '.$bibentry->getField('chapter');} + if ($type=="article") { + $booktitle = 'In '.$bibentry->getField("journal");} + + //// we may add the editor names to the booktitle + $editor=''; + if ($bibentry->hasField(EDITOR)) { + $editor = $bibentry->getFormattedEditors(); + } + if ($editor!='') $booktitle .=' ('.$editor.')'; + // end editor section + + // is the booktitle available + if ($booktitle!='') { + $entry[] = '
    '.$booktitle.''; + } + + + $publisher=''; + if ($type=="phdthesis") { + $publisher = 'PhD thesis, '.$bibentry->getField(SCHOOL); + } + if ($type=="mastersthesis") { + $publisher = 'Master\'s thesis, '.$bibentry->getField(SCHOOL); + } + if ($type=="bachelorsthesis") { + $publisher = 'Bachelor\'s thesis, '.$bibentry->getField(SCHOOL); + } + if ($type=="techreport") { + $publisher = 'Technical report, '.$bibentry->getField("institution"); + } + + if ($type=="misc") { + $publisher = $bibentry->getField('howpublished'); + } + + if ($bibentry->hasField("publisher")) { + $publisher = $bibentry->getField("publisher"); + } + + if ($publisher!='') $entry[] = ''.$publisher.''; + + + if ($bibentry->hasField('volume')) $entry[] = "volume ".$bibentry->getField("volume"); + + + if ($bibentry->hasField(YEAR)) $entry[] = $bibentry->getYear(); + + $result = implode(", ",$entry).'.'; + + // some comments (e.g. acceptance rate)? + if ($bibentry->hasField('comment')) { + $result .= " (".$bibentry->getField("comment").")"; + } + if ($bibentry->hasField('note')) { + $result .= " (".$bibentry->getField("note").")"; + } + + // add the Coin URL + //$result .= "\n".$bibentry->toCoins(); + $result .= "
    \n"; + + // we add biburl and title to be able to retrieve this important information + // using Xpath expressions on the XHTML source + $result .= $bibentry->getBibLink(); + // returns an empty string if no pdf present + $result .= $bibentry->getLink('pdf'); + // returns an empty string if no url present + $result .= $bibentry->getLink('url'); + // returns an empty string if no slides present + $result .= $bibentry->getLink('slides'); + // returns an empty string if no poster present + $result .= $bibentry->getLink('poster'); + // Google Scholar ID. empty string if no gsid present + $result .= $bibentry->getGSLink(); + // returns an empty string if no doi present + $result .= $bibentry->getDoiLink(); + + $result .= '
    '; + + return $result; +} + +/** Class to display a bibliography of a page. */ +class BibliographyDisplay { + /** the bib entries to display. */ + var $result; + + /** the content strategy (cf. pattern strategy) */ + var $contentStrategy; + + /** the query to reinject in links to different pages */ + var $filter; + + /** Creates an instance with the given entries and header. */ + function BibliographyDisplay(&$result, $filter) { + $this->result = $result; + $this->filter = $filter; + // requesting a different page of the result view? + $this->setTitle(); + $this->contentStrategy = new BibliographyContentStrategy(); + } + + /** sets the $this->title of BibtexBrowserDisplay based on the $filter */ + function setTitle() { + $this->title = query2title($this->filter); + } + + /** overrides */ + function formatedHeader() { return '
    '.$this->title.' '.createRSSLink($this->filter).'
    ';} + + /** overrides */ + function getURL() { return '?'.createQueryString($this->filter);} + + /** overrides */ + function getRSS() { return BIBTEXBROWSER_URL.'?'.createQueryString($this->filter).'&rss';} + + /** Displays the entries preceded with the header. */ + function display() { + // print error message if no entry. + if (empty($this->result)) { + echo "No references.\n"; + return; + } + $this->contentStrategy->display($this); + echo $this->poweredby(); + if (BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT) { + $this->javascript(); + } + } + + + function poweredby() { + $poweredby = "\n".'
    '; + $poweredby .= ''; + $poweredby .= 'Powered by bibtexbrowser'; + $poweredby .= '
    '."\n"; + return $poweredby; + } + + /** Adds a touch of AJAX in bibtexbrowser to display bibtex entries inline. + * It uses the HIJAX design pattern: the Javascript code fetches the normal bibtex HTML page + * and extracts the bibtex. + * In other terms, URLs and content are left perfectly optimized for crawlers + * Note how beautiful is this piece of code thanks to JQuery. + */ + function javascript() { + // we use jquery with the official content delivery URLs + // Microsoft and Google also provide jquery with their content delivery networks +?> + +
      + + + +
      + result; + $refnum = count($display->result); + + foreach ($entries as $value => $bib) { + $bib->setAbbrv($value); + switch(LAYOUT) { + case 'list': $bib->toLI(); break; + case 'table': $bib->toTR(); break; + case 'deflist': $bib->toDD(); break; + } + } // end foreach + + switch(LAYOUT) { + case 'list': + ?> + + +
      + + + + diff --git a/bibtexbrowser.php b/bibtexbrowser.php index 45f7513..e757c4f 100644 --- a/bibtexbrowser.php +++ b/bibtexbrowser.php @@ -1,9 +1,284 @@ -URL: http://www.monperrus.net/martin/bibtexbrowser/ -Feedback & Bug Reports: martin.monperrus@gmail.com + + +bibtexbrowser is a PHP script that creates publication lists from Bibtex files. + bibtexbrowser is stable, mature and easy to install. It is used in [[users|60+ different universities]] around the globe. + ++++TOC+++ + +=====Major features===== +* **(11/2009)** bibtexbrowser generates [[http://www.monperrus.net/martin/accurate+bibliographic+metadata+and+google+scholar|Google Scholar metadata]] so as to improve the visibility of your papers on Google Scholar. Since Google has now [[http://scholar.google.com/intl/en/scholar/inclusion.html|documented this feature]], as of version ≥20100621, Google Scholar Metadata should be completely correct. +* **(11/2009)** More and more academics use bibliographic software like [[http://www.zotero.org/|Zotero]] or [[http://www.mendeley.com/|Mendeley]]. bibtexbrowser generates [[http://ocoins.info/|COinS]] for automatic import of bibliographic entries with [[http://www.zotero.org/|Zotero]] and [[http://www.mendeley.com/|Mendeley]]. +* **(10/2009)** People can subscribe to the RSS publication feed of an individual or a group so as to being kept up-to-date: bibtexbrowser generates RSS feeds for all queries (simply add &rss at the end of the URL)! [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=monperrus.bib&all&rss|demo]] +* **(02/2009)** bibtexbrowser can display all entries for an author with an academic style (i.e book, articles, conference, workshop): [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&academic=Ducasse|demo]] +* **(05/2008)**: bibtexbrowser can be used to embed a publication list into another page: [[http://www.monperrus.net/martin/|demo]] +* **(04/2007)**: bibtexbrowser is easy to install: just a single file. + +=====Other features===== +* **(10/2011)** if a bibtex entry contains a field gsid (like Google Scholar ID), bibtexbrowser includes a link [cites] to the cited-by page of Google Scholar (e.g. [[http://scholar.google.com/scholar?cites=15080874515065717592]]) +* **(03/2011)** bibtexbrowser includes a hide/show mechanism for bibtex entries (in Javascript, see configuration variable BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT) +* **(10/2010)** bibtexbrowser now supports cross-references (Bibtex crossref) +* **(09/2010)** bibtexbrowser now supports multiple bibtex files (''bibtexbrowser.php?bib=file1.bib;file2.bib'') +* **(05/2010)** bibtexbrowser adds links to your co-author pages if you define the corresponding @string (see function addHomepageLink) +* **(01/2010)** bibtexbrowser can handle user-defined bibliographic styles +* **(10/2009)** bibtexbrowser is able to generate a bibtex file containing only the selected entries (simply add &astext at the end of the link) +* **(10/2009)** bibtexbrowser is now independent of the configuration of register_globals +* **(01/2009)** bibtexbrowser allows multi criteria search, e.g. [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&type=inproceedings&year=2004|demo]] +* bibtexbrowser replaces constants defined in @STRING +* bibtexbrowser is very fast because it keeps a compiled version of the bibtex file (PHP object serialized) +* bibtexbrowser is compatible with PHP 4.x and PHP 5.x +* bibtexbrowser can display the menu and all entries without filtering from the file name passed as parameter [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib|demo]] +* bibtexbrowser can display all entries out of a bibtex file [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&all|demo]] +* bibtexbrowser can display all entries for a given year [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&year=2004|demo]] +* bibtexbrowser can display a single bibtex entry [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&key=monperrus08d|demo]] +* bibtexbrowser can display found entries with a search word (it can be in any bib field) [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&search=ocl|demo]] +* bibtexbrowser can display all entries with a bib keyword +* bibtexbrowser outputs valid XHTML 1.0 Transitional +* bibtexbrowser can display all entries for an author [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&author=Barbara+A.+Kitchenham|demo]] +* bibtexbrowser can be used with different encodings (change the default iso-8859-1 encoding if your bib file is in UTF-8 ''define('ENCODING','UTF-8')'' ) + + +=====Download===== +For feature requests, bug reports, or patch proposals, [[http://www.monperrus.net/martin/|please drop me an email ]] or comment this page. Don't hesitate to contact me to be added in the [[users|lists of bibtexbrowser users]] :-) + +You may try bibtexbrowser without installation by uploading your bibtex file at [[http://my.publications.li]]. + +**[[http://www.monperrus.net/martin/bibtexbrowser.php.txt|Download bibtexbrowser]]** (Try the release candidate!)';} ?> + + +=====Demo and screenshot===== + +Demo: [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib|Here, you can browse a bibtex file dedicated to software metrics]] + +bibtexbrowser screenshot + +=====Basic installation===== +
      +Create a bib file with the publication records (e.g. csgroup2008.bib) and upload it to your server. +* Use the link ''bibtexbrowser.php?bib=csgroup2008.bib'' (frameset based view) +* Use the link ''bibtexbrowser.php?bib=csgroup2008.bib&all'' (pub list sorted by year) +* Use the link ''bibtexbrowser.php?bib=csgroup2008.bib&all&academic'' (pub list sorted by publication type, then by year, see "Sectioning in academic mode" below) + +** Warning **: bibtexbrowser maintains a cached version of the parsed bibtex, for high performance, check that PHP can write in the working directory of PHP. + +**Handling mutliple bibtex files**: If you want to include several bibtex files, just give bibtexbrowser the files separated by semi-columns e.g: +''bibtexbrowser.php?bib=strings.bib;csgroup2008.bib'' + +
      + +=====UTF-8 support / ISO-8859-1 support===== + +^^By default, bibtexbrowser assumes that the bibtex file is UTF-8 encoded. +If you want to change it to e.g. ISO-8859-1, add ''define('ENCODING','ISO-8859-1');'' into ''bibtexbrowser.local.php'' (see below). +Note that if the bibtex only contains latex-encoded diacritics (e.g. ''\'e''), it does not matter. +^^ +=====How to embed your publication list in your home page===== +
      + + + + + + + + + + + +
      Sorted by year Sorted by publication type
      For a group/team/lab +<?php +$_GET['bib']='csgroup2008.bib'; +$_GET['all']=1; +include( 'bibtexbrowser.php' ); +?> + +<?php +$_GET['bib']='csgroup2008.bib'; +$_GET['all']=1; +define('ABBRV_TYPE','year'); +$_GET['academic']=1; +include( 'bibtexbrowser.php' ); +?> +
      For an individual + <?php +$_GET['bib']='mybib.bib'; +$_GET['author']='Martin Monperrus'; +include( 'bibtexbrowser.php' ); +?> + +<?php +$_GET['bib']='mybib.bib'; +$_GET['author']='Martin Monperrus'; +define('ABBRV_TYPE','year'); +$_GET['academic']=1; +include( 'bibtexbrowser.php' ); +?> +
      +
      + +=====Sectioning in academic mode===== + +The default academic mode creates four sections : +- books +- articles and book chapters +- workshop papers (for entries containing "workshop" in the field booktitle) +- others. + +You may create your own one in ''bibtexbrowser.local.php'' (see also "By creating a bibtexbrowser.local.php" below): +
      +define('BIBLIOGRAPHYSECTIONS','my_sectioning');
      +function my_sectioning() {
      +return  
      +  array(
      +  // Books
      +    array(
      +      'query' => array(Q_TYPE=>'book'),
      +      'title' => 'Books'
      +    ),
      +  // Articles
      +    array(
      +      'query' => array(Q_TYPE=>'article'),
      +      'title' => 'Refereed Articles'
      +    ),
      +  // Conference and Workshop papers
      +    array(
      +      'query' => array(Q_TYPE=>'inproceedings),
      +      'title' => 'Conference and Workshop  Papers'
      +    ),
      +  // others
      +    array(
      +      'query' => array(Q_TYPE=>'misc|phdthesis|mastersthesis|bachelorsthesis|techreport'),
      +      'title' => 'Other Publications'
      +    )
      +  );
      +}
      +
      + +=====How to tailor bibtexbrowser?===== + +====By modifying the CSS==== +
      + +If bibtexbrowser.css exists, it is used, otherwise bibtexbrowser uses its own embedded CSS style (see function bibtexbrowserDefaultCSS). An example of CSS tailoring is: +
      +.date {   background-color: blue; }
      +.rheader {  font-size: large }
      +.bibref {  padding:3px; padding-left:15px;  vertical-align:top;}
      +.bibtitle { font-weight:bold; }
      +.bibbooktitle { font-style:italic; }
      +
      +
      + +====By modifying the bibliography style ==== +
      +The bibliography style is encapsulated in a function. If you want to modify the bibliography style, you can copy the default style ([[bibtexbrowser-style-default.php.txt|source]]) in a new file, say ''bibtexbrowser-yourstyle.php'', and rename the function ''DefaultBibliographyStyle'' in say ''MyFancyBibliographyStyle''. +Then, add in the file ''bibtexbrowser.local.php'' (see below): + +<?php +include( 'bibtexbrowser-yourstyle.php' ); +define('BIBLIOGRAPHYSTYLE','MyFancyBibliographyStyle'); +?> + + +[[http://www.monperrus.net/martin/bibtexbrowser-style-janos.php.txt|Janos Tapolcai contributed with this style, which looks like IEEE references]]. +For contributing with a new style, [[http://www.monperrus.net/martin/|please drop me an email ]] +
      + +====By creating a bibtexbrowser.local.php==== +
      + +All the variable parts of bibtexbrowser can be modified with a file called ''bibtexbrowser.local.php''. + +
      +<?php
      +// ------------------------------- NOVICE LEVEL
      +// if your bibtex file is UTF-8 encodedd
      +// define("ENCODING","UTF-8");
      +
      +// number of bib items per page
      +// define('PAGE_SIZE',50);
      +
      +// disable Javascript progressive enhancement
      +// define('BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT',false);
      +
      +// may be default/year/x-abbrv
      +// default => [1] The essence of metamodeling
      +// year => [2005] The essence of metamodeling
      +// x-abbrv => [SoSyM] The essence of metamodeling if the bibtex entry contains a field x-abbrv
      +//define('ABBRV_TYPE','default');
      +
      +// see the other define(...) in the source, they are all overridable
      +
      +// ------------------------------- INTERMEDIATE LEVEL
      +
      +// if you are not satisifed with the default style
      +// define('BIBLIOGRAPHYSTYLE','MyFancyBibliographyStyle');
      +function MyFancyBibliographyStyle() {
      +   // see function DefaultBibliographyStyle
      +}
      +
      +// if you are not satisifed with the default sections
      +// define('BIBLIOGRAPHYSECTIONS','mySections');
      +function mySections() {
      +return  
      +  array(
      +  // Books
      +    array(
      +      'query' => array(Q_TYPE=>'book'),
      +      'title' => 'Cool Books'
      +    ),
      +  // .. see function DefaultBibliographySections
      +);
      +}
      +
      +
      +// ------------------------------- EXPERT LEVEL
      +// define('BIBTEXBROWSER_URL','path/to/bibtexbrowser.php'); // if bibtexbrowser.php is in another directory in embedded mode
      +// define('BIBTEXBROWSER_URL',''); // to get the individual bib pages embedded as well
      +
      +?>
      +
      +
      + + + +=====How to add links to the slides of a conference/workshop paper?===== + +You can simply fill the ''comment'' field of the bib entry with an HTML link: + +@inproceedings{foo, +author="Jean Dupont", +title="Bibtexbrowser", +year=2009, +booktitle="Proceedings of the BIB conference", +comment={<a href="myslides.pdf">[slides]</a>} +} + + +This comment field can also be used to add acceptance rates and impact factors. + +=====Related tools===== + +Old-fashioned: +[[http://nxg.me.uk/dist/bibhtml/|bibhtml]], [[http://www.litech.org/~wkiri/bib2html/|bib2html]], [[http://ilab.usc.edu/bibTOhtml/|bibtohtml]], [[http://people.csail.mit.edu/rahimi/bibtex/|bibtextohtml]], [[http://www.lri.fr/~filliatr/bibtex2html/|bibtex2html]], [[http://people.csail.mit.edu/mernst/software/bibtex2web.html |bibtex2web]], [[http://strategoxt.org/Stratego/BibtexTools|stratego bibtex module]] +Unlike them, **bibtexbrowser is dynamic**.i.e.; generates the HTML pages on the fly. Thus, you do not need to regenerate the static HTML files each time the bib file is changed. + +Heavyweight: +[[http://www.rennes.supelec.fr/ren/perso/etotel/PhpBibtexDbMng/|PHP BibTeX Database Manager]], [[http://gforge.inria.fr/projects/bibadmin/|bibadmin]], [[http://artis.imag.fr/Software/Basilic/|basilic]], [[http://phpbibman.sourceforge.net/|phpbibman]], [[http://www.aigaion.nl/|aigaion]], [[http://www.refbase.net/|refbase]], [[http://wikindx.sourceforge.net/|wikindx]], [[http://refdb.sourceforge.net/|refdb]] +Unlike them, **bibtexbrowser does not need a MySQL database** -(C) 2006-2012 Martin Monperrus + +Main competitor: +[[http://code.google.com/p/simplybibtex/|SimplyBibtex]] has the same spirit, but the project seems dead since 2006 + +Misc: +[[http://www.sat.ltu.se/publications/publications.m|This matlab script is similar]] + +=====Copyright===== + +This script is a fork from an excellent script of the University of Texas at El Paso. + +(C) 2006-2011 Martin Monperrus (C) 2005-2006 The University of Texas at El Paso / Joel Garcia, Leonardo Ruiz, and Yoonsik Cheon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -12,26 +287,23 @@ License, or (at your option) any later version. */ -// it is be possible to include( 'bibtexbrowser.php' ); several times in the same script -// added on Wednesday, June 01 2011, bug found by Carlos Bras +// Wednesday, June 01 2011: bug found by Carlos Br�s +// it should be possible to include( 'bibtexbrowser.php' ); several times in the same script if (!defined('BIBTEXBROWSER')) { // this if block ends at the very end of this file, after all class and function declarations. -define('BIBTEXBROWSER','v20121205'); +define('BIBTEXBROWSER','v20111211'); // *************** CONFIGURATION // I recommend to put your changes in bibtexbrowser.local.php // it will help you to upgrade the script with a new version -// 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__)); - +@include(dirname(__FILE__).'/bibtexbrowser.local.php'); // 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 @define('ENCODING','UTF-8');//@define('ENCODING','iso-8859-1');//define('ENCODING','windows-1252'); // number of bib items per page -// we use the same parameter 'num' as Google -@define('PAGE_SIZE',isset($_GET['num'])?(preg_match('/^\d+$/',$_GET['num'])?$_GET['num']:10000):14); +@define('PAGE_SIZE',isset($_GET['nopage'])?10000:25); // bibtexbrowser uses a small piece of Javascript to improve the user experience // see http://en.wikipedia.org/wiki/Progressive_enhancement // if you don't like it, you can be disable it by adding in bibtexbrowser.local.php @@ -46,40 +318,11 @@ define('BIBTEXBROWSER','v20121205'); // can we load bibtex files on external servers? @define('BIBTEXBROWSER_LOCAL_BIB_ONLY', true); -// the default view in {SimpleDisplay,AcademicDisplay,RSSDisplay,BibtexDisplay} -@define('BIBTEXBROWSER_DEFAULT_DISPLAY','SimpleDisplay'); - // the target frame of menu links @define('BIBTEXBROWSER_MENU_TARGET','main'); // might be define('BIBTEXBROWSER_MENU_TARGET','_self'); in bibtexbrowser.local.php -@define('ABBRV_TYPE','index');// may be year/x-abbrv/key/none/index - -// 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'); - -// only displaying the n newest entries -@define('BIBTEXBROWSER_NEWEST',5); - -@define('BIBTEXBROWSER_NO_DEFAULT', false); - -// do we add [bibtex] links ? -// suggested by Sascha Schnepp -@define('BIBTEXBROWSER_BIBTEX_LINKS',true); - -// should authors be linked to [none/homepage/resultpage] -// none: nothing -// their homepage if defined as @strings -// their publication lists according to this bibtex -@define('BIBTEXBROWSER_AUTHOR_LINKS','homepage'); - -@define('BIBTEXBROWSER_DEBUG',false); +@define('ABBRV_TYPE','default');// may be default/year/x-abbrv +@define('LAYOUT','table'); // MG: may be table/list/deflist. defines the HTML rendering options (,
        ,
        , resp.). 'list' only works with 'ABBRV_TYPE'='default'. @define('COMMA_NAMES',false);// do have authors in a comma separated form? @define('TYPES_SIZE',10); // number of entry types per table @@ -94,17 +337,18 @@ define('BIBTEXBROWSER','v20121205'); @define('Q_AUTHOR_PAGE', 'author_page'); @define('Q_TAG', 'keywords'); @define('Q_TAG_PAGE', 'keywords_page'); -@define('Q_TYPE', 'type');// used for queries +@define('Q_TYPE', 'type'); @define('Q_TYPE_PAGE', 'type_page'); @define('Q_ALL', 'all'); @define('Q_ENTRY', 'entry'); @define('Q_KEY', 'key'); +@define('Q_KEYS', 'keys'); @define('Q_SEARCH', 'search'); +@define('Q_BIBLIOGRAPHY', 'bibliography'); @define('Q_EXCLUDE', 'exclude'); @define('Q_RESULT', 'result'); @define('Q_ACADEMIC', 'academic'); @define('Q_DB', 'bibdb'); -@define('Q_LATEST', 'latest'); @define('AUTHOR', 'author'); @define('EDITOR', 'editor'); @define('SCHOOL', 'school'); @@ -125,9 +369,6 @@ define('BIBTEXBROWSER','v20121205'); // *************** 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 @@ -137,48 +378,15 @@ define('Q_INNER_TYPE', 'x-bibtex-type');// used for representing the type of the // we ensure that the pages won't get polluted // if future versions of PHP change warning mechanisms... - @error_reporting(E_ERROR); -/** parses $_GET[Q_FILE] and puts the result (an object of type BibDataBase) in $_GET[Q_DB]. -See also zetDB(). +/** sets the database of bibtex entries (object of type BibDataBase) + * in $_GET[Q_DB] + * Uses a caching mechanism on disk for sake of performance */ function setDB() { - list($db, $parsed, $updated, $saved) = _zetDB(@$_GET[Q_FILE]); - $_GET[Q_DB] = $db; - return $updated; -} - -/** parses the $bibtex_filenames (usually semi-column separated) and returns an object of type BibDataBase. -See also setDB() -*/ -function zetDB($bibtex_filenames) { - list($db, $parsed, $updated, $saved) = _zetDB($bibtex_filenames); - return $db; -} - -/** @nodoc */ -function default_message() { - if (BIBTEXBROWSER_NO_DEFAULT) { return; } - - ?> -
        - Congratulations! bibtexbrowser is correctly installed!
        - Now you have to pass the name of the bibtex file as parameter (e.g. bibtexbrowser.php?bib=mybib.php)
        - You may browse:
        - '.$bibfile.'
        '; - } - echo "
        "; -} - -/** @nodoc */ -function _zetDB($bibtex_filenames) { - - $db = null; // Check if magic_quotes_runtime is active if(get_magic_quotes_runtime()) { @@ -188,18 +396,27 @@ function _zetDB($bibtex_filenames) { } // default bib file, if no file is specified in the query string. - if (!isset($bibtex_filenames) || $bibtex_filenames == "") { - default_message(); - exit; + if (!isset($_GET[Q_FILE]) || $_GET[Q_FILE] == "") { + ?> +
        + Congratulations! bibtexbrowser is correctly installed!
        + Now you have to pass the name of the bibtex file as parameter (e.g. bibtexbrowser.php?bib=mybib.php)
        + You may browse:
        + '.$bibfile.'
        '; + } + echo "
        "; + return; // we cannot set the db wtihout a bibfile } // first does the bibfiles exist: - // $bibtex_filenames can be urlencoded for instance if they contain slashes + // $_GET[Q_FILE] can be urlencoded for instance if they contain slashes // so we decode it - $bibtex_filenames = urldecode($bibtex_filenames); + $_GET[Q_FILE] = urldecode($_GET[Q_FILE]); // ---------------------------- HANDLING unexistent files - foreach(explode(MULTIPLE_BIB_SEPARATOR, $bibtex_filenames) as $bib) { + foreach(explode(MULTIPLE_BIB_SEPARATOR, $_GET[Q_FILE]) as $bib) { // this is a security protection if (BIBTEXBROWSER_LOCAL_BIB_ONLY && !file_exists($bib)) { @@ -216,7 +433,7 @@ function _zetDB($bibtex_filenames) { // save bandwidth and server cpu // (imagine the number of requests from search engine bots...) $bib_is_unmodified = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ; - foreach(explode(MULTIPLE_BIB_SEPARATOR, $bibtex_filenames) as $bib) { + foreach(explode(MULTIPLE_BIB_SEPARATOR, $_GET[Q_FILE]) as $bib) { $bib_is_unmodified = $bib_is_unmodified && (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])>filemtime($bib)); @@ -231,341 +448,270 @@ function _zetDB($bibtex_filenames) { // ---------------------------- HANDLING caching of compiled bibtex files // for sake of performance, once the bibtex file is parsed // we try to save a "compiled" in a txt file - $compiledbib = 'bibtexbrowser_'.md5($bibtex_filenames).'.dat'; + $compiledbib = 'bibtexbrowser_'.md5($_GET[Q_FILE]).'.dat'; - $parse=filemtime(__FILE__)>@filemtime($compiledbib); - + $parse=false; + foreach(explode(MULTIPLE_BIB_SEPARATOR, $_GET[Q_FILE]) as $bib) { // do we have a compiled version ? - if (is_file($compiledbib) - && is_readable($compiledbib) - && filesize($compiledbib)>0 - ) { - $f = fopen($compiledbib,'r'); - //we use a lock to avoid that a call to bibbtexbrowser made while we write the object loads an incorrect object - if (flock($f,LOCK_EX)) { - $s = filesize($compiledbib); - $ser = fread($f,$s); - $db = @unserialize($ser); - flock($f,LOCK_UN); - } else { die('could not get the lock'); } - fclose($f); - // basic test - // do we have an correct version of the file - if (!is_a($db,'BibDataBase')) { - unlink($compiledbib); - if (BIBTEXBROWSER_DEBUG) { die('$db not a BibDataBase. please reload.'); } - $parse=true; - } + if (is_file($compiledbib) && is_readable($compiledbib)) { + // is it up to date ? wrt to the bib file and the script + // then upgrading with a new version of bibtexbrowser triggers a new compilation of the bib file + if (filemtime($bib)'; // then parsing the file - $db = createBibDataBase(); - foreach(explode(MULTIPLE_BIB_SEPARATOR, $bibtex_filenames) as $bib) { + $db = new BibDataBase(); + foreach(explode(MULTIPLE_BIB_SEPARATOR, $_GET[Q_FILE]) as $bib) { $db->load($bib); } - } + $_GET[Q_DB]=$db; + + // are we able to save the compiled version ? + // note that the compiled version is saved in the current working directory + if ((!is_file($compiledbib) && is_writable(getcwd())) || (is_file($compiledbib) && is_writable($compiledbib)) ) { + // we can use file_put_contents + // but don't do it for compatibility with PHP 4.3 + $f = fopen($compiledbib,'w'); + //we use a lock to avoid that a call to bbtexbrowser made while we write the object loads an incorrect object + if (flock($f,LOCK_EX)) fwrite($f,serialize($_GET[Q_DB])); + fclose($f); + } + //else echo ''; + } // end parsing and saving - $updated = false; - // now we may update the database - if (!file_exists($compiledbib)) { - @touch($compiledbib); - $updated = true; // limit case - } else foreach(explode(MULTIPLE_BIB_SEPARATOR, $bibtex_filenames) as $bib) { - // is it up to date ? wrt to the bib file and the script - // then upgrading with a new version of bibtexbrowser triggers a new compilation of the bib file - if (filemtime($bib)>filemtime($compiledbib) || filemtime(__FILE__)>filemtime($compiledbib)) { -// echo "updating ".$bib; - $db->update($bib); - $updated = true; - } - } - -// echo var_export($parse); -// echo var_export($updated); - - $saved = false; - // are we able to save the compiled version ? - // note that the compiled version is saved in the current working directory - if ( ($parse || $updated ) && is_writable($compiledbib)) { - // we use 'a' because the file is not locked between fopen and flock - $f = fopen($compiledbib,'a'); - //we use a lock to avoid that a call to bibbtexbrowser made while we write the object loads an incorrect object - if (flock($f,LOCK_EX)) { -// echo ''; - ftruncate($f,0); - fwrite($f,serialize($db)); - flock($f,LOCK_UN); - $saved = true; - } else { die('could not get the lock'); } - fclose($f); - } // end saving the cached verions - //else echo ''; - - - return array(&$db, $parse, $updated, $saved); + return $parse; } // end function setDB -// factories -// may be overridden in bibtexbrowser.local.php -if (!function_exists('createBibDataBase')) { - /** factory method for openness @nodoc */ - function createBibDataBase() { $x = new BibDataBase(); return $x;} -} -if (!function_exists('createBibEntry')) { - /** factory method for openness @nodoc */ - function createBibEntry() { $x = new BibEntry(); return $x;} -} -if (!function_exists('createBibDBBuilder')) { - /** factory method for openness @nodoc */ - function createBibDBBuilder() { $x = new BibDBBuilder(); return $x;} -} -if (!function_exists('createBasicDisplay')) { - /** factory method for openness @nodoc */ - function createBasicDisplay() { $x = new SimpleDisplay(); return $x;} -} -if (!function_exists('createBibEntryDisplay')) { - /** factory method for openness @nodoc */ - function createBibEntryDisplay() { $x = new BibEntryDisplay(); return $x;} -} -if (!function_exists('createMenuManager')) { - /** factory method for openness @nodoc */ - function createMenuManager() { $x = new MenuManager(); return $x;} -} + //////////////////////////////////////////////////////// -/** is a generic parser of bibtex files. -usage: -
        -  $delegate = new XMLPrettyPrinter();// or another delegate such as BibDBBuilder
        -  $parser = new StateBasedBibtexParser($delegate);
        -  $parser->parse('foo.bib');
        -
        -notes: - - It has no dependencies, it can be used outside of bibtexbrowser - - The delegate is expected to have some methods, see classes BibDBBuilder and XMLPrettyPrinter +/** This class is a generic parser of bibtex files + * It has no dependencies, i.e. it can be used outside of bibtexbrowser + * To use it, simply instantiate it and pass it an object that will receive semantic events + * The delegate is expected to have some methods + * see classes BibDBBuilder and XMLPrettyPrinter */ class StateBasedBibtexParser { - - var $delegate; - - function StateBasedBibtexParser(&$delegate) { - $this->delegate = &$delegate; - } - - function parse($bibfilename) { - $delegate = &$this->delegate; - // STATE DEFINITIONS - @define('NOTHING',1); - @define('GETTYPE',2); - @define('GETKEY',3); - @define('GETVALUE',4); - @define('GETVALUEDELIMITEDBYQUOTES',5); - @define('GETVALUEDELIMITEDBYQUOTES_ESCAPED',6); - @define('GETVALUEDELIMITEDBYCURLYBRACKETS',7); - @define('GETVALUEDELIMITEDBYCURLYBRACKETS_ESCAPED',8); - @define('GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL',9); - @define('GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL_ESCAPED',10); - @define('GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL',11); - @define('GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL_ESCAPED',12); - @define('GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL',13); - @define('GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED',14); - - - $state=NOTHING; - $entrytype=''; - $entrykey=''; - $entryvalue=''; - $finalkey=''; - $entrysource=''; - - // metastate - $isinentry = false; - - $delegate->beginFile(); - - $handle = fopen($bibfilename, "r"); - if (!$handle) die ('cannot open '.$bibfilename); - // if you encounter this error "Allowed memory size of xxxxx bytes exhausted" - // then decrease the size of the temp buffer below - $bufsize=BUFFERSIZE; - while (!feof($handle)) { - $sread=fread($handle,$bufsize); - //foreach(str_split($sread) as $s) { - for ( $i=0; $i < strlen( $sread ); $i++) { $s=$sread[$i]; - - if ($isinentry) $entrysource.=$s; - - if ($state==NOTHING) { - // this is the beginning of an entry - if ($s=='@') { - $delegate->beginEntry(); - $state = GETTYPE; - $isinentry = true; - $entrysource='@'; - } - } - - else if ($state==GETTYPE) { - // this is the beginning of a key - if ($s=='{') { - $state = GETKEY; - $delegate->setEntryType($entrytype); - $entrytype=''; - } - else $entrytype=$entrytype.$s; - } - - else if ($state==GETKEY) { - // now we get the value - if ($s=='=') { - $state = GETVALUE; - $finalkey=$entrykey; - $entrykey='';} - // oups we only have the key :-) anyway - else if ($s=='}') { - $state = NOTHING;$isinentry = false;$delegate->endEntry($entrysource); - $entrykey=''; - } - // OK now we look for values - else if ($s==',') { - $state=GETKEY; - $delegate->setEntryKey($entrykey); - $entrykey='';} - else { $entrykey=$entrykey.$s; } - } - // we just got a =, we can now receive the value, but we don't now whether the value - // is delimited by curly brackets, double quotes or nothing - else if ($state==GETVALUE) { - // the value is delimited by double quotes - if ($s=='"') { - $state = GETVALUEDELIMITEDBYQUOTES; - } - // the value is delimited by curly brackets - else if ($s=='{') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS; - } - // the end of the key and no value found: it is the bibtex key e.g. \cite{Descartes1637} - else if ($s==',') { - $state = GETKEY; - $delegate->setEntryField(trim($finalkey),$entryvalue); - $entryvalue=''; // resetting the value buffer - } - // this is the end of the value AND of the entry - else if ($s=='}') { - $state = NOTHING; - $delegate->setEntryField(trim($finalkey),$entryvalue); - $isinentry = false;$delegate->endEntry($entrysource); - $entryvalue=''; // resetting the value buffer - } - else if ($s==' ' || $s=="\t" || $s=="\n" || $s=="\r" ) { - // blank characters are not taken into account when values are not in quotes or curly brackets - } - else { $entryvalue=$entryvalue.$s;} - } +function StateBasedBibtexParser($bibfilename, &$delegate) { + + +// STATE DEFINITIONS +@define('NOTHING',1); +@define('GETTYPE',2); +@define('GETKEY',3); +@define('GETVALUE',4); +@define('GETVALUEDELIMITEDBYQUOTES',5); +@define('GETVALUEDELIMITEDBYQUOTES_ESCAPED',6); +@define('GETVALUEDELIMITEDBYCURLYBRACKETS',7); +@define('GETVALUEDELIMITEDBYCURLYBRACKETS_ESCAPED',8); +@define('GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL',9); +@define('GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL_ESCAPED',10); +@define('GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL',11); +@define('GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL_ESCAPED',12); +@define('GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL',13); +@define('GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED',14); + + +$state=NOTHING; +$entrytype=''; +$entrykey=''; +$entryvalue=''; +$finalkey=''; +$entrysource=''; + +// metastate +$isinentry = false; + +$delegate->beginFile(); + +$handle = fopen($bibfilename, "r"); +if (!$handle) die ('cannot open '.$bibfilename); +// if you encounter this error "Allowed memory size of xxxxx bytes exhausted" +// then decrease the size of the temp buffer below +$bufsize=BUFFERSIZE; +while (!feof($handle)) { +$sread=fread($handle,$bufsize); +//foreach(str_split($sread) as $s) { +for ( $i=0; $i < strlen( $sread ); $i++) { $s=$sread[$i]; + + if ($isinentry) $entrysource.=$s; + + if ($state==NOTHING) { + // this is the beginning of an entry + if ($s=='@') { + $delegate->beginEntry(); + $state = GETTYPE; + $isinentry = true; + $entrysource='@'; + } + } + else if ($state==GETTYPE) { + // this is the beginning of a key + if ($s=='{') { + $state = GETKEY; + $delegate->setEntryType($entrytype); + $entrytype=''; + } + else $entrytype=$entrytype.$s; + } - /* GETVALUEDELIMITEDBYCURLYBRACKETS* handle entries delimited by curly brackets and the possible nested curly brackets */ - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS) { + else if ($state==GETKEY) { + // now we get the value + if ($s=='=') { + $state = GETVALUE; + $finalkey=$entrykey; + $entrykey='';} + // oups we only have the key :-) anyway + else if ($s=='}') { + $state = NOTHING;$isinentry = false;$delegate->endEntry($entrysource); + $entrykey=''; + } + // OK now we look for values + else if ($s==',') { + $state=GETKEY; + $delegate->setEntryKey($entrykey); + $entrykey='';} + else { $entrykey=$entrykey.$s; } + } + // we just got a =, we can now receive the value, but we don't now whether the value + // is delimited by curly brackets, double quotes or nothing + else if ($state==GETVALUE) { + + // the value is delimited by double quotes + if ($s=='"') { + $state = GETVALUEDELIMITEDBYQUOTES; + } + // the value is delimited by curly brackets + else if ($s=='{') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS; + } + // the end of the key and no value found: it is the bibtex key e.g. \cite{Descartes1637} + else if ($s==',') { + $state = GETKEY; + $delegate->setEntryField(trim($finalkey),$entryvalue); + $entryvalue=''; // resetting the value buffer + } + // this is the end of the value AND of the entry + else if ($s=='}') { + $state = NOTHING; + $delegate->setEntryField(trim($finalkey),$entryvalue); + $isinentry = false;$delegate->endEntry($entrysource); + $entryvalue=''; // resetting the value buffer + } + else if ($s==' ' || $s=="\t" || $s=="\n" || $s=="\r" ) { + // blank characters are not taken into account when values are not in quotes or curly brackets + } + else { $entryvalue=$entryvalue.$s;} + } + + +/* GETVALUEDELIMITEDBYCURLYBRACKETS* handle entries delimited by curly brackets and the possible nested curly brackets */ + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS) { + + if ($s=='\\') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_ESCAPED; + $entryvalue=$entryvalue.$s;} + else if ($s=='{') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL;$entryvalue=$entryvalue.$s;} + else if ($s=='}') { + $state = GETVALUE;} + else { $entryvalue=$entryvalue.$s;} + } + // handle anti-slashed brackets + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_ESCAPED) { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS; + $entryvalue=$entryvalue.$s; + } + // in first level of curly bracket + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL) { + if ($s=='\\') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL_ESCAPED; + $entryvalue=$entryvalue.$s;} + else if ($s=='{') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL;$entryvalue=$entryvalue.$s;} + else if ($s=='}') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS;$entryvalue=$entryvalue.$s;} + else { $entryvalue=$entryvalue.$s;} + } + // handle anti-slashed brackets + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL_ESCAPED) { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL; + $entryvalue=$entryvalue.$s; + } + + // in second level of curly bracket + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL) { + if ($s=='\\') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL_ESCAPED; + $entryvalue=$entryvalue.$s;} + else if ($s=='{') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL;$entryvalue=$entryvalue.$s;} + else if ($s=='}') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL;$entryvalue=$entryvalue.$s;} + else { $entryvalue=$entryvalue.$s;} + } + // handle anti-slashed brackets + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL_ESCAPED) { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL; + $entryvalue=$entryvalue.$s; + } + + // in third level of curly bracket + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL) { + if ($s=='\\') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED; + $entryvalue=$entryvalue.$s;} + else if ($s=='}') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL;$entryvalue=$entryvalue.$s;} + else { $entryvalue=$entryvalue.$s;} + } + // handle anti-slashed brackets + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED) { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL; + $entryvalue=$entryvalue.$s; + } - if ($s=='\\') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_ESCAPED; - $entryvalue=$entryvalue.$s;} - else if ($s=='{') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL;$entryvalue=$entryvalue.$s;} - else if ($s=='}') { - $state = GETVALUE;} - else { $entryvalue=$entryvalue.$s;} - } - // handle anti-slashed brackets - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_ESCAPED) { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS; - $entryvalue=$entryvalue.$s; - } - // in first level of curly bracket - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL) { - if ($s=='\\') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL_ESCAPED; - $entryvalue=$entryvalue.$s;} - else if ($s=='{') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL;$entryvalue=$entryvalue.$s;} - else if ($s=='}') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS;$entryvalue=$entryvalue.$s;} - else { $entryvalue=$entryvalue.$s;} - } - // handle anti-slashed brackets - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL_ESCAPED) { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL; - $entryvalue=$entryvalue.$s; - } +/* handles entries delimited by double quotes */ + else if ($state==GETVALUEDELIMITEDBYQUOTES) { - // in second level of curly bracket - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL) { - if ($s=='\\') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL_ESCAPED; - $entryvalue=$entryvalue.$s;} - else if ($s=='{') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL;$entryvalue=$entryvalue.$s;} - else if ($s=='}') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL;$entryvalue=$entryvalue.$s;} - else { $entryvalue=$entryvalue.$s;} - } - // handle anti-slashed brackets - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL_ESCAPED) { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL; - $entryvalue=$entryvalue.$s; - } - - // in third level of curly bracket - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL) { - if ($s=='\\') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED; - $entryvalue=$entryvalue.$s;} - else if ($s=='}') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL;$entryvalue=$entryvalue.$s;} - else { $entryvalue=$entryvalue.$s;} - } - // handle anti-slashed brackets - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED) { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL; - $entryvalue=$entryvalue.$s; - } - - /* handles entries delimited by double quotes */ - else if ($state==GETVALUEDELIMITEDBYQUOTES) { - - if ($s=='\\') { - $state = GETVALUEDELIMITEDBYQUOTES_ESCAPED; - $entryvalue=$entryvalue.$s;} - else if ($s=='"') { - $state = GETVALUE; - } - else { $entryvalue=$entryvalue.$s;} - } - // handle anti-double quotes - else if ($state==GETVALUEDELIMITEDBYQUOTES_ESCAPED) { - $state = GETVALUEDELIMITEDBYQUOTES; - $entryvalue=$entryvalue.$s; - } + if ($s=='\\') { + $state = GETVALUEDELIMITEDBYQUOTES_ESCAPED; + $entryvalue=$entryvalue.$s;} + else if ($s=='"') { + $state = GETVALUE; + } + else { $entryvalue=$entryvalue.$s;} + } + // handle anti-double quotes + else if ($state==GETVALUEDELIMITEDBYQUOTES_ESCAPED) { + $state = GETVALUEDELIMITEDBYQUOTES; + $entryvalue=$entryvalue.$s; + } - } // end for - } // end while - $delegate->endFile(); - fclose($handle); - //$d = &$this->delegate;print_r($d); - } // end function +} // end for +} // end while +$delegate->endFile(); +fclose($handle); +} // end function } // end class -/** is a delegate for StateBasedBibParser. -usage: -see snippet of [[#StateBasedBibParser]] -*/ +/** This class can be used together with StateBasedBibParser */ class XMLPrettyPrinter { function beginFile() { header('Content-type: text/xml;'); @@ -598,49 +744,23 @@ class XMLPrettyPrinter { } } // end class XMLPrettyPrinter -/** builds arrays of BibEntry objects from a bibtex file. -usage: -
        -  $empty_array = array();
        -  $db = new BibDBBuilder(); // see also factory method createBibDBBuilder
        -  $db->build('foo.bib'); // parses foo.bib
        -  print_r($db->builtdb);// an associated array key -> BibEntry objects
        -  print_r($db->stringdb);// an associated array key -> strings representing @string
        -
        -notes: - method build can be used several times, bibtex entries are accumulated in the builder -*/ +/** This class can be used together with StateBasedBibParser */ class BibDBBuilder { /** A hashtable from keys to bib entries (BibEntry). */ - var $builtdb = array(); + var $builtdb; /** A hashtable of constant strings */ - var $stringdb = array(); - - var $filename; + var $stringdb; var $currentEntry; - function setData(&$builtdb, &$stringdb) { + function BibDBBuilder($filename, &$builtdb, &$stringdb) { $this->builtdb = $builtdb; $this->stringdb = $stringdb; - return $this; + new StateBasedBibtexParser($filename, $this); } - function build($filename) { - $this->filename = $filename; - $parser = new StateBasedBibtexParser($this); - $parser->parse($filename); - //print_r(array_keys(&$this->builtdb)); - //print_r(&$this->builtdb); - } - - - function getBuiltDb() { - //print_r($this->builtdb); - return $this->builtdb; - } function beginFile() { } @@ -664,7 +784,6 @@ class BibDBBuilder { } } } - //print_r($this->builtdb); } function setEntryField($finalkey,$entryvalue) { @@ -703,27 +822,18 @@ class BibDBBuilder { } function beginEntry() { - $this->currentEntry = createBibEntry(); - $this->currentEntry->setFile($this->filename); + $this->currentEntry = new BibEntry(); } function endEntry($entrysource) { - // 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 + // we can 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(Q_INNER_AUTHOR,$this->currentEntry->getFormattedAuthorsImproved()); + $this->currentEntry->setField('_author',$this->currentEntry->getFormattedAuthorsImproved()); } // ignoring jabref comments @@ -734,13 +844,13 @@ class BibDBBuilder { // we add it to the string database else if ($this->currentEntry->getType()=='string') { foreach($this->currentEntry->fields as $k => $v) { - $k!=Q_INNER_TYPE and $this->stringdb[$k]=$v; + $k!='type' and $this->stringdb[$k]=$v; } } // we add it to the database else { - $this->builtdb[$this->currentEntry->getKey()] = $this->currentEntry; + $this->builtdb[$this->currentEntry->getKey()] = $this->currentEntry; } } } // end class BibDBBuilder @@ -748,7 +858,8 @@ class BibDBBuilder { -/** is an extended version of the trim function, removes linebreaks, tabs, etc. +/** extended version of the trim function + * removes linebreaks, tabs, etc. */ function xtrim($line) { $line = trim($line); @@ -766,25 +877,22 @@ function xtrim($line) { return $line; } -/** encapsulates the conversion of a single latex chars to the corresponding HTML entity. -It expects a **lower-case** char. -*/ +/** encapsulates the conversion of a single latex chars to the corresponding HTML entity + * this works thanks to the regularity of html entities + * it expects a **lower** char + */ function char2html($line,$latexmodifier,$char,$entitiyfragment) { - $line = char2html_case_sensitive($line,$latexmodifier,strtoupper($char),$entitiyfragment); - return char2html_case_sensitive($line,$latexmodifier,strtolower($char),$entitiyfragment); -} - -function char2html_case_sensitive($line,$latexmodifier,$char,$entitiyfragment) { -// old version -// $line = str_replace('\\'.$latexmodifier.$char,'&'.$char.''.$entitiyfragment.';', $line); -// $line = str_replace('\\'.$latexmodifier.' '.$char,'&'.$char.''.$entitiyfragment.';', $line); -// $line = str_replace('\\'.$latexmodifier.'{'.$char.'}','&'.$char.''.$entitiyfragment.';', $line); - $line = preg_replace('/\\\\'.preg_quote($latexmodifier,'/').' ?\\{?'.$char.'\\}?/','&'.$char.''.$entitiyfragment.';', $line); + $line = str_replace('\\'.$latexmodifier.$char,'&'.$char.''.$entitiyfragment.';', $line); + $line = str_replace('\\'.$latexmodifier.'{'.$char.'}','&'.$char.''.$entitiyfragment.';', $line); + $line = str_replace('\\'.$latexmodifier.strtoupper($char),'&'.strtoupper($char).''.$entitiyfragment.';', $line); + $line = str_replace('\\'.$latexmodifier.'{'.strtoupper($char).'}','&'.strtoupper($char).''.$entitiyfragment.';', $line); return $line; } -/** converts latex chars to HTML entities. -(I still look for a comprehensive translation table from late chars to html, better than [[http://isdc.unige.ch/Newsletter/help.html]]) +/** converts latex chars to HTML entities + * it uses a naive algortihm + * I still look for a comprehensive translation table from late chars to html + * just have this http://isdc.unige.ch/Newsletter/help.html */ function latex2html($line) { $line = preg_replace('/([^\\\\])~/','\\1 ', $line); @@ -843,7 +951,6 @@ function latex2html($line) { $line = char2html($line,'.','a',"ring"); $line = char2html($line,'c','c',"cedil"); - $line = char2html($line,'v','s',"caron"); $line = str_replace('\\ae','æ', $line); $line = str_replace('\\ss','ß', $line); @@ -860,14 +967,10 @@ function latex2html($line) { return $line; } -/** encodes strings for Z3988 URLs. Note that & are encoded as %26 and not as &. */ +/** Note that & are encoded as %26 and not as & so it does not break the Z3988 URL */ function s3988($s) {return urlencode(utf8_encode($s));} -/** -see BibEntry->formatAuthor($author) -@deprecated -@nodoc -*/ +/** @deprecated */ function formatAuthor() { die('Sorry, this function does not exist anymore, however, you can simply use $bibentry->formatAuthor($author) instead.'); } @@ -876,16 +979,9 @@ function formatAuthor() { // BIB ENTRIES // ---------------------------------------------------------------------- -/** represents a bibliographic entry. -usage: -
        -  $db = zetDB('metrics.bib');
        -  $entry = $db->getEntryByKey('Schmietendorf2000');
        -  echo bib2html($entry);
        -
        -notes: -- BibEntry are usually obtained with getEntryByKey or multisearch -*/ +/** + * Class to represent a bibliographic entry. + */ class BibEntry { /** The fields (fieldName -> value) of this bib entry. */ @@ -900,23 +996,6 @@ class BibEntry { /** The verbatim copy (i.e., whole text) of this bib entry. */ var $text; - /** A timestamp to trace when entries have been created */ - var $timestamp; - - /** The name of the file containing this entry */ - var $filename; - - /** The short name of the entry (parameterized by ABBRV_TYPE) */ - var $abbrv; - - /** The index in a list of publications (e.g. [1] Foo */ - var $index = ''; - - /** returns a debug string representation */ - function __toString() { - return $this->getType()." ".$this->getKey(); - } - /** Creates an empty new bib entry. Each bib entry is assigned a unique * identification number. */ function BibEntry() { @@ -925,30 +1004,17 @@ class BibEntry { $this->text =''; } - /** Sets the name of the file containing this entry */ - function setFile($filename) { - $this->filename = $filename; - return $this; - } - - /** Adds timestamp to this object */ - function setTimestamp() { - $this->timestamp = time(); - } - /** Returns the timestamp of this object */ - function getTimestamp() { - return $this->timestamp; - } - /** Returns the type of this bib entry. */ function getType() { // strtolower is important to be case-insensitive - return strtolower($this->getField(Q_INNER_TYPE)); + return strtolower($this->getField(Q_TYPE)); } /** Sets the key of this bib entry. */ function setKey($value) { - $this->setField(Q_KEY,$value); + $this->setField('key',$value); + // by default the ID is the key + $this->id = $value; } /** Sets a field of this bib entry. */ @@ -974,10 +1040,8 @@ class BibEntry { // to support space e.g. "@article {" // as generated by ams.org // thanks to Jacob Kellner - $this->fields[Q_INNER_TYPE] =trim($value); + $this->fields[Q_TYPE] =trim($value); } - - function setIndex($index) { $this->index = $index; } /** Tries to build a good URL for this entry */ function getURL() { @@ -985,9 +1049,7 @@ class BibEntry { $f = BIBTEXBROWSER_URL_BUILDER; return $f($this); } -// echo $this->filename; -// echo $this->getKey(); - return BIBTEXBROWSER_URL.'?'.createQueryString(array(Q_KEY=>$this->getKey(), Q_FILE=>$this->filename)); + return BIBTEXBROWSER_URL.'?'.createQueryString(array('key'=>$this->getKey())); } /** Tries to build a good absolute URL for this entry */ @@ -999,26 +1061,67 @@ class BibEntry { return "http://".$_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME']).'/'.$this->getURL(); } - /** returns a "[pdf]" link if relevant */ - function getUrlLink() { - if ($this->hasField('url')) return ' [pdf]'; + /** MG: replace [$ext] with an icon whose url is defined in a string + * e.g. getIconOrTxt('pdf') will show the icon defined by @string{icon_pdf="http://mywebsite/pdf.png"} or print '[pdf]' + * or getIconOrTxt('pdf','paper') will show the icon defined by @string{icon_pdf="http://mywebsite/pdf.png"} or print '[paper]' + * Warning: by convention @string are case sensitive + */ + function getIconOrTxt($ext,$def=NULL) { + // e.g. @STRING{icon_pdf="http://mywebsite/pdf.png"} + if ($def==NULL) { $def=$ext; } + $stringkey = strtolower('icon_'.$ext); + if (isset($_GET[Q_DB]->stringdb[$stringkey])){ + $str='['.$def.']'; + } else { + $str='['.$def.']'; + } + return $str; + } + + /** MG: Read the url specified as the bibtex entry key $bibentry and return the link with icon or text + * e.g. given the bibtex entry: @article{myarticle, pdf={myarticle.pdf}}, + * $bibtexentry->getLink('pdf') creates a link to myarticle.pdf using the text '[pdf]' or the pdf icon specified in the bibtex file (cf. getIconOrTxt) + * getLink($bibentry,$icon,$def) specifies the icon key $icon and default text $def. + */ + function getLink($bibentry,$icon=NULL,$def=NULL) { + if ($icon==NULL) { $icon=$bibentry; } + $str = $this->getIconOrTxt($icon,$def); + if ($this->hasField($bibentry)) { + return ' '.$str.''; + } return ''; } + /** MG: DOI are a special kind of links, where the url depends on the doi */ + function getDoiLink() { + $str = $this->getIconOrTxt('doi'); + if ($this->hasField('doi')) { + return ' '.$str.''; + } + return ''; + } + + /** MG: GS are a special kind of links, where the url depends on the google scholar id */ + function getGSLink() { + $str = $this->getIconOrTxt('gsc','cites'); + // Google Scholar ID + if ($this->hasField('gsid')) { + return ' '.$str.''; + } + return ''; + } + + /** returns a "[url]" link if relevant */ /* MG: modified to exploit the new method, while keeping backward compatibility */ + function getUrlLink() { + return $this->getLink('url'); + } + /** Reruns the abstract */ function getAbstract() { if ($this->hasField('abstract')) return $this->getField('abstract'); else return ''; } - /** - * Returns the last name of an author name. - */ - function getLastName($author){ - list($firstname, $lastname) = splitFullName($author); - return $lastname; - } - /** Has this entry the given field? */ function hasField($name) { @@ -1041,7 +1144,7 @@ class BibEntry { /** Returns the key of this entry */ function getKey() { - return $this->getField(Q_KEY); + return $this->getField('key'); } /** Returns the title of this entry? */ @@ -1111,7 +1214,7 @@ class BibEntry { } - /** Returns the authors as an array of strings (one string per author) */ + /** Returns the authors as a string depending on the configuration parameter COMMA_NAMES */ function getFormattedAuthors() { $authors = array(); foreach ($this->getRawAuthors() as $author) { @@ -1125,35 +1228,18 @@ class BibEntry { */ function formattedAuthors() { return $this->getFormattedAuthorsImproved(); } - /** Adds to getFormattedAuthors() the home page links and returns a string (not an array). Is configured with BIBTEXBROWSER_AUTHOR_LINKS and COMMA_NAMES. + /** Adds to getFormattedAuthors() the home page links and returns a string (not an array) */ function getFormattedAuthorsImproved() { $array_authors = $this->getFormattedAuthors(); - - if (BIBTEXBROWSER_AUTHOR_LINKS=='homepage') { - foreach ($array_authors as $k => $author) { - $array_authors[$k]=$this->addHomepageLink($author); - } - } - - if (BIBTEXBROWSER_AUTHOR_LINKS=='resultpage') { - foreach ($array_authors as $k => $author) { - $array_authors[$k]=$this->addAuthorPageLink($author); - } + foreach ($array_authors as $k => $author) { + $array_authors[$k]=$this->addHomepageLink($author); } if (COMMA_NAMES) {$sep = '; ';} else {$sep = ', ';} - return implode($sep ,$array_authors); } - /** adds a link to the author page */ - function addAuthorPageLink($author) { - $link = makeHref(array(Q_AUTHOR => $author)); - return "$author"; - } - - /** Returns the authors of this entry as an array in a canonical form */ function getCanonicalAuthors() { $authors = array(); @@ -1177,7 +1263,7 @@ class BibEntry { * all author names except for the first one and appending ", et al." */ function getCompactedAuthors($author){ - $authors = $this->getRawAuthors(); + $authors = $this->getAuthors(); $etal = count($authors) > 1 ? ', et al.' : ''; return $this->formatAuthor($authors[0]) . $etal; } @@ -1218,7 +1304,8 @@ class BibEntry { if (COMMA_NAMES) {$sep = '; ';} else {$sep = ', ';} return implode($sep, $editors).', '.(count($editors)>1?'eds.':'ed.'); } - + + /** Returns the year of this entry? */ function getYear() { return $this->getField('year'); @@ -1241,29 +1328,29 @@ class BibEntry { function getFields() { return $this->fields; } - + + /** Returns the identification number. */ + function getId() { + return $this->id; + } + /** Returns the abbreviation. */ function getAbbrv() { - if (ABBRV_TYPE == 'index') return $this->index; - if (ABBRV_TYPE == 'none') return ''; - if (ABBRV_TYPE == 'key') return '['.$this->getKey().']'; - if (ABBRV_TYPE == 'year') return '['.$this->getYear().']'; + if (ABBRV_TYPE == 'default') return $this->id; + if (ABBRV_TYPE == 'year') return $this->getYear(); if (ABBRV_TYPE == 'x-abbrv') { if ($this->hasField('x-abbrv')) {return $this->getField('x-abbrv');} - return $this->abbrv; - } + // otherwise + return $this->getKey(); + } - // otherwise it is a user-defined function in bibtexbrowser.local.php - $f = ABBRV_TYPE; - return $f($this); + die('Unknown configuration value for ABBRV_TYPE'); } /** Sets the abbreviation (e.g. [OOPSLA] or [1]) */ function setAbbrv($abbrv) { - //if (!is_string($abbrv)) { throw new Exception('Illegal argument'); } - $this->abbrv = $abbrv; - return $this; + return $this->id = $abbrv; } function getText() { @@ -1271,7 +1358,7 @@ class BibEntry { return $this->text; } - /** Returns true if this bib entry contains the given phrase (PREG regexp) + /** Returns true if this bib entry contains the given phrase * 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) { @@ -1296,37 +1383,40 @@ class BibEntry { } + /** returns a "[bib]" link if relevant */ + /** MG: added the Bib icon */ + function getBibLink() { + $bibstr = $this->getIconOrTxt('bib'); + $href = 'href="'.$this->getURL().'"'; + $link = "getKey()."\" {$href}>$bibstr"; + return $link; + } + + /** Outputs an HTML line (
      )with two TDS inside */ function toTR() { echo ''; - echo ' '; + echo ' '; echo '\n"; + } - $href = 'href="'.$this->getURL().'"'; - if (BIBTEXBROWSER_BIBTEX_LINKS) { - // we add biburl and title to be able to retrieve this important information - // using Xpath expressions on the XHTML source - echo " getKey()."\" {$href}>[bibtex]"; - } - - // returns an empty string if no url present - echo $this->getUrlLink(); + /** MG: Outputs an LI line (
    1. ) with spans for each element, using the value attribute the abbrev. (does not work with x-abbrv) */ + function toLI() { + echo '
    2. '; + echo ''; + echo bib2html($this); + echo "
    3. \n"; + } - if ($this->hasField('doi')) { - echo ' [doi]'; - } - - // Google Scholar ID - if ($this->hasField('gsid')) { - echo ' [cites]'; - } - echo "\n"; + /** MG: Outputs an DL line (
      +
      ) */ + function toDD() { + echo '
      '.$this->getAbbrv().'
      '; + echo bib2html($this); + echo "
      \n"; } /** Outputs an coins URL: see http://ocoins.info/cobg.html @@ -1378,8 +1468,8 @@ class BibEntry { } // referrer, the id pf a collection of objects - // see also http://www.openurl.info/registry/docs/pdf/info-sid.pdf - $url_parts[]='rfr_id='.s3988('info:sid/'.$_SERVER['HTTP_HOST'].':'.@$_GET[Q_FILE]); + // see also http://www.openurl.info/registry/docs/pdf/info-sid.pdf + $url_parts[]='rfr_id='.s3988('info:sid/'.$_SERVER['HTTP_HOST'].':'.$_GET[Q_FILE]); $url_parts[]='rft.date='.s3988($this->getYear()); @@ -1442,41 +1532,18 @@ function bib2html(&$bibentry) { return $function($bibentry); } -/** encapsulates the user-defined sections. @nodoc */ +/**bibtexbrowser uses this function which encapsulates the user-defined sections*/ function _DefaultBibliographySections() { $function = BIBLIOGRAPHYSECTIONS; return $function(); } -/** compares two instances of BibEntry by modification time - */ -function compare_bib_entry_by_mtime($a, $b) -{ - return -($a->getTimestamp()-$b->getTimestamp()); -} -/** compares two instances of BibEntry by year - */ -function compare_bib_entry_by_year_and_month($a, $b) -{ - $year_cmp = -strcmp($a->getYear(),$b->getYear()); - if ($year_cmp==0) { return compare_bib_entry_by_month($a, $b);} - return $year_cmp; -} - -/** compares two instances of BibEntry by title - */ -function compare_bib_entry_by_title($a, $b) -{ - return strcmp($a->getTitle(),$b->getTitle()); -} - - -/** compares two instances of BibEntry by month +/** Compares two instances of BibEntry by month * @author Jan Geldmacher */ function compare_bib_entry_by_month($a, $b) -{ +{ // this was the old behavior // return strcmp($a->getKey(),$b->getKey()); @@ -1507,15 +1574,15 @@ function compare_bib_entry_by_month($a, $b) $val_a = array_search(strtolower($a->fields[$sort_key]), $sort_order_values); $val_b = array_search(strtolower($b->fields[$sort_key]), $sort_order_values); - if (($val_a === FALSE && $val_b === FALSE) || ($val_a === $val_b)) { + if (($val_a == FALSE && $val_b == FALSE) || ($val_a == $val_b)) { //neither a nor b are in the search array or a=b -> both are equal $retval=0; } - elseif (($val_a === FALSE) || ($val_a < $val_b)) { + elseif (($val_a == FALSE) || ($val_a < $val_b)) { //a is not in the search array or a b is greater $retval=-1; } - elseif (($val_b === FALSE) || (($val_a > $val_b))){ + elseif (($val_b == FALSE) || (($val_a > $val_b))){ //b is not in the search array or a>b -> a is greater $retval=1; } @@ -1524,24 +1591,19 @@ function compare_bib_entry_by_month($a, $b) return $order*$retval; } -/** is the default sectioning for AcademicDisplay (books, articles, proceedings, etc. ) */ +/** the default sections */ function DefaultBibliographySections() { return array( // Books array( - 'query' => array(Q_TYPE=>'book|proceedings'), + 'query' => array(Q_TYPE=>'book'), 'title' => 'Books' ), - // Book chapters - array( - 'query' => array(Q_TYPE=>'incollection|inbook'), - 'title' => 'Book Chapters' - ), // Journal / Bookchapters array( - 'query' => array(Q_TYPE=>'article'), - 'title' => 'Refereed Articles' + 'query' => array(Q_TYPE=>'article|incollection'), + 'title' => 'Refereed Articles and Book Chapters' ), // conference papers array( @@ -1562,13 +1624,20 @@ return } -/** transforms a $bibentry into an HTML string. - It is called by function bib2html if the user did not choose a specific style - the default usable CSS styles are - .bibtitle { font-weight:bold; } - .bibbooktitle { font-style:italic; } - .bibauthor { } - .bibpublisher { } +?>getTitle(); @@ -1663,104 +1732,7 @@ function DefaultBibliographyStyle(&$bibentry) { } - -/** is the Bibtexbrowser style contributed by Janos Tapolcai. It looks like the IEEE transaction style. -usage: -Add the following line in "bibtexbrowser.local.php" -
      -define('BIBLIOGRAPHYSTYLE','JanosBibliographyStyle');
      -
      -*/ -function JanosBibliographyStyle(&$bibentry) { - $title = $bibentry->getTitle(); - $type = $bibentry->getType(); - - $entry=array(); - - // author - if ($bibentry->hasField('author')) { - $entry[] = $bibentry->formattedAuthors(); - } - - // title - $title = '"'.$title.'"'; - if ($bibentry->hasField('url')) $title = ' '.$title.''; - $entry[] = $title; - - - // now the origin of the publication is in italic - $booktitle = ''; - - if (($type=="misc") && $bibentry->hasField("note")) { - $booktitle = $bibentry->getField("note"); - } - - if ($type=="inproceedings") { - $booktitle = 'In '.$bibentry->getField(BOOKTITLE); - } - - if ($type=="incollection") { - $booktitle = 'Chapter in '.$bibentry->getField(BOOKTITLE); - } - - if ($type=="article") { - $booktitle = 'In '.$bibentry->getField("journal"); - } - - - - //// ******* EDITOR - $editor=''; - if ($bibentry->hasField(EDITOR)) { - $editor = $bibentry->getFormattedEditors(); - } - - if ($booktitle!='') { - if ($editor!='') $booktitle .=' ('.$editor.')'; - $entry[] = ''.$booktitle.''; - } - - - $publisher=''; - if ($type=="phdthesis") { - $publisher = 'PhD thesis, '.$bibentry->getField(SCHOOL); - } - - if ($type=="mastersthesis") { - $publisher = 'Master\'s thesis, '.$bibentry->getField(SCHOOL); - } - if ($type=="techreport") { - $publisher = 'Technical report, '.$bibentry->getField("institution"); - } - if ($bibentry->hasField("publisher")) { - $publisher = $bibentry->getField("publisher"); - } - - if ($publisher!='') $entry[] = $publisher; - - if ($bibentry->hasField('volume')) $entry[] = "vol. ".$bibentry->getField("volume"); - if ($bibentry->hasField('number')) $entry[] = 'no. '.$bibentry->getField("number"); - - if ($bibentry->hasField('address')) $entry[] = $bibentry->getField("address"); - - if ($bibentry->hasField('pages')) $entry[] = str_replace("--", "-", "pp. ".$bibentry->getField("pages")); - - - if ($bibentry->hasField(YEAR)) $entry[] = $bibentry->getYear(); - - $result = implode(", ",$entry).'.'; - - // some comments (e.g. acceptance rate)? - if ($bibentry->hasField('comment')) { - $result .= " (".$bibentry->getField("comment").")"; - } - - // add the Coin URL - $result .= "\n".$bibentry->toCoins(); - - return $result; -} - +?> $val) { - // 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; } + if($key == '_author') { $key = 'author'; } $array_param[$key]=$key .'='. urlencode($val); } return implode("&",$array_param); } -/** returns a href string of the form: href="?bib=testing.bib&search=JML. -Based on createQueryString. -@nodoc +/** + * Given a query, an array of key value pairs, returns a href string + * of the form: href="?bib=testing.bib&search=JML. */ function makeHref($query = NULL) { return 'href="?'. createQueryString($query) .'"'; } +/** + * Returns the last name of an author name. + */ +function getLastName($author){ + list($firstname, $lastname) = splitFullName($author); + return $lastname; +} -/** returns the splitted name of an author name as an array. The argument is assumed to be - "FirstName LastName" or "LastName, FirstName". +/** + * Returns the splitted name of an author name as an array. The argument is assumed to be + * or . */ function splitFullName($author){ $author = trim($author); @@ -1820,16 +1798,17 @@ function splitFullName($author){ } -/** outputs an horizontal year-based menu -usage: -
      -  $_GET['library']=1;
      -  $_GET['bib']='metrics.bib';
      -  $_GET['all']=1;
      -  include( 'bibtexbrowser.php' );
      -  setDB();
      -  new IndependentYearMenu();
      -
      +/** New undocumented feature, used by Benoit Baudry + * see http://www.irisa.fr/triskell/perso_pro/bbaudry/publications.php + * + * $_GET['library']=1; + * $_GET['bib']='metrics.bib'; + * $_GET['all']=1; + * include( 'bibtexbrowser.php' ); + * setDB(); + * new IndependentYearMenu(); + * new Dispatcher(); + * */ class IndependentYearMenu { function IndependentYearMenu() { @@ -1848,29 +1827,45 @@ class IndependentYearMenu { } } -/** Returns the powered by part. @nodoc */ -function poweredby() { - $poweredby = "\n".'
      '; - $poweredby .= ''; - $poweredby .= 'Powered by bibtexbrowser'; - $poweredby .= '
      '."\n"; - return $poweredby; - } +/** Class to encapsulates the header formatting and the powered by footer */ +class BibtexBrowserDisplay { + /** the title */ + var $title; + function getTitle() { return $this->title; } -/** ^^adds a touch of AJAX in bibtexbrowser to display bibtex entries inline. - It uses the HIJAX design pattern: the Javascript code fetches the normal bibtex HTML page - and extracts the bibtex. - In other terms, URLs and content are left perfectly optimized for crawlers - Note how beautiful is this piece of code thanks to JQuery.^^ - */ -function javascript() { + function display() { /* unimplemented */ } + + /** returns the url of this display (e.g. base on the query)*/ + function getURL() { return '';} + + /** returns the url of the RSS */ + function getRSS() { return '';} + + /** Returns the powered by part */ + function poweredby() { + $poweredby = "\n".'
      '; + $poweredby .= ''; + $poweredby .= 'Powered by bibtexbrowser'; + $poweredby .= '
      '."\n"; + return $poweredby; + } + + function formatedHeader() { return "
      {$this->title}
      \n";} + + /** Adds a touch of AJAX in bibtexbrowser to display bibtex entries inline. + * It uses the HIJAX design pattern: the Javascript code fetches the normal bibtex HTML page + * and extracts the bibtex. + * In other terms, URLs and content are left perfectly optimized for crawlers + * Note how beautiful is this piece of code thanks to JQuery. + */ + function javascript() { // we use jquery with the official content delivery URLs // Microsoft and Google also provide jquery with their content delivery networks ?> - $db = zetDB('metrics.bib'); - $menu = new MenuManager(); - $menu->setDB($db); - $menu->year_size=100;// should display all years :) - $menu->display(); - +/** + * A class providing GUI controllers in a frame. */ -class MenuManager { +class MenuManager extends BibtexBrowserDisplay { /** The bibliographic database, an instance of class BibDataBase. */ var $db; - var $type_size = TYPES_SIZE; - var $year_size = YEAR_SIZE; - var $author_size = AUTHORS_SIZE; - var $tag_size = TAGS_SIZE; - - function MenuManager() { - } - - /** sets the database that is used to create the menu */ - function setDB(&$db) { + /** Creates a new display manager that uses the given bib database. */ + function MenuManager(&$db) { $this->db =$db; - return $this; } - function getTitle() { - return ''; - } - - /** function called back by HTMLWrapper */ function display() { echo $this->searchView().'
      '; @@ -1968,18 +1942,18 @@ class MenuManager { /** Displays and controls the types menu in a table. */ function typeVC() { - $types = array(); - foreach ($this->db->getTypes() as $type) { - $types[$type] = $type; - } - $types['.*'] = 'all types'; + $types = array(); + $types[''] = 'all types'; + foreach ($this->db->getTypes() as $type) { + $types[$type] = $type; + } // 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_INNER_TYPE); + $this->displayMenu('Types', $types, $page, TYPES_SIZE, Q_TYPE_PAGE, Q_TYPE); } /** Displays and controls the authors menu in a table. */ @@ -1994,7 +1968,7 @@ class MenuManager { else $page = 1; - $this->displayMenu('Authors', $authors, $page, $this->author_size, Q_AUTHOR_PAGE, + $this->displayMenu('Authors', $authors, $page, AUTHORS_SIZE, Q_AUTHOR_PAGE, Q_AUTHOR); } @@ -2009,7 +1983,7 @@ class MenuManager { } else $page = 1; - if (count($tags)>0) $this->displayMenu('Keywords', $tags, $page, $this->tag_size, Q_TAG_PAGE, + if (count($tags)>0) $this->displayMenu('Keywords', $tags, $page, TAGS_SIZE, Q_TAG_PAGE, Q_TAG); } @@ -2022,10 +1996,10 @@ class MenuManager { if (isset($_GET[Q_YEAR_PAGE])) { $page = $_GET[Q_YEAR_PAGE]; } -else $page = 1; + else $page = 1; - $this->displayMenu('Years', $years, $page, $this->year_size, Q_YEAR_PAGE, + $this->displayMenu('Years', $years, $page, YEAR_SIZE, Q_YEAR_PAGE, Q_YEAR); } @@ -2055,9 +2029,9 @@ else $page = 1;
      '; - //echo ''; - - echo $this->getAbbrv().'['.$this->getAbbrv().']'; echo bib2html($this); + echo "
      - - - + + @@ -2065,7 +2039,7 @@ else $page = 1; - @@ -2086,19 +2060,31 @@ else $page = 1; $start, $end) { $result = ''; + /* // commented after the usability remarks of Benoit Combemale + // fast (2 pages) reverse (<<) + if ($start - $pageSize > 0) { + $href = makeHref(array($queryKey => $page - 2,'menu'=>'')); + $result .= '«\n"; + }*/ // (1 page) reverse (<) if ($start > 0) { - $href = makeHref(array($queryKey => $page - 1,'menu'=>''));//menuPageBar + $href = makeHref(array($queryKey => $page - 1,'menu'=>'')); $result .= '[prev]\n"; } // (1 page) forward (>) if ($end < $numEntries) { - $href = makeHref(array($queryKey => $page + 1,'menu'=>''));//menuPageBar + $href = makeHref(array($queryKey => $page + 1,'menu'=>'')); $result .= '[next]\n"; } + /*// commented after the usability remarks of Benoit Combemale + // fast (2 pages) forward (>>) + if (($end + $pageSize) < $numEntries) { + $href = makeHref(array($queryKey => $page + 2,'menu'=>'')); + $result .= '»\n"; + }*/ return $result; } @@ -2107,7 +2093,7 @@ else $page = 1; * the end index (exclusive). For each menu, the following form of * string is printed: * - * + * * Cheon, Yoonsik *
      */ @@ -2124,280 +2110,375 @@ else $page = 1; } } -if (!function_exists('query2title')) { /** transforms an array representing a query into a formatted string */ function query2title(&$query) { + if (isset($query[Q_BIBLIOGRAPHY])) return 'Publications in ' . $_SERVER['PHP_SELF']; $headers = array(); foreach($query as $k=>$v) { - 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(htmlspecialchars($v)); + if($k == '_author') { $k = 'author'; } + if($k == 'type') { $v = substr($v,1,strlen($v)-2); } + $headers[$k] = ucwords($k).': '.ucwords($v); } // special cases - if (isset($headers[Q_ALL])) $headers[Q_ALL] = 'Publications in '.htmlspecialchars($_GET[Q_FILE]); - if (isset($headers[Q_AUTHOR])) $headers[Q_AUTHOR] = 'Publications of '.htmlspecialchars($_GET[Q_AUTHOR]); + if (isset($headers[Q_ALL])) $headers[Q_ALL] = 'Publications in '.$_GET[Q_FILE]; + if (isset($headers[Q_AUTHOR])) $headers[Q_AUTHOR] = 'Publications of '.$_GET[Q_AUTHOR]; return join(' & ',$headers); } -} -/** displays the latest modified bibtex entries. -usage: -
      -  $db = zetDB('metrics.bib');
      -  $d = new NewEntriesDisplay();
      -  $d->setDB($db);
      -  $d->setN(7);// optional 
      -  $d->display();
      -
      - */ -class NewEntriesDisplay { - var $n=5; - var $db; - - function setDB(&$bibdatabase) { - $this->db = $bibdatabase; + +/** Class to display a result as a set of pages. */ +class PagedDisplay extends BibtexBrowserDisplay { + /** the bib entries to display. */ + var $result; + + /** the page number to display. */ + var $page; + + /** the total number of pages to display. */ + var $noPages; + + /** the start index to display. */ + var $startIndex; + + /** the end index to display. */ + var $endIndex; + + /** the content strategy (cf. pattern strategy) */ + var $contentStrategy; + + /** the query to reinject in links to different pages */ + var $filter; + + /** Creates an instance with the given entries and header. */ + function PagedDisplay(&$result, $filter) { + $this->result = $result; + $this->filter = $filter; + // requesting a different page of the result view? + if (isset($_GET[Q_RESULT])) { + $this->setPage($_GET[Q_RESULT]); + } else $this->page = 1; + $this->setTitle(); + $this->contentStrategy = new DefaultContentStrategy(); } - - function setN($n) {$this->n = $n;return $this;} - /** sets the entries to be shown */ - function setEntries(&$entries) { - $this->db = createBibDataBase(); - $this->db->bibdb = $entries; + /** sets the $this->title of BibtexBrowserDisplay based on the $filter */ + function setTitle() { + $this->title = query2title($this->filter); + if ($this->page>1) $this->title.=' - page '.$this->page; + } + + /** Sets the page number to display. */ + function setPage($page) { + $this->page = $page; + } + + /** overrides */ + function formatedHeader() { return '
      '.$this->title.' '.createRSSLink($this->filter).'
      ';} + + /** overrides */ + function getURL() { return '?'.createQueryString($this->filter);} + + /** overrides */ + function getRSS() { return BIBTEXBROWSER_URL.'?'.createQueryString($this->filter).'&rss';} + + /** Displays the entries preceded with the header. */ + function display() { + + $page = $this->page; + + // print error message if no entry. + if (empty($this->result)) { + echo "No match found!\n"; + return; + } + + $this->noPages = ceil(count($this->result) / PAGE_SIZE); + + if ($this->noPages>1) $this->displayPageBar($this->noPages, $page); + + $this->startIndex = ($page - 1) * PAGE_SIZE; + $this->endIndex =$this->startIndex + PAGE_SIZE; + // $this->setLayout(); + + $this->contentStrategy->display($this); + if ($this->noPages>1) $this->displayPageBar($this->noPages, $page); + + echo $this->poweredby(); + + if (BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT) { + $this->javascript(); + } + } - /** Displays a set of bibtex entries in an HTML table */ - function display() { - $array = $this->db->getLatestEntries($this->n); - $delegate = createBasicDisplay(); - $delegate->setEntries($array); - $delegate->display(); + function isDisplayed($index) { + if ($index >= $this->startIndex && $index < $this->endIndex) return true; + return false; } -} -/** displays the entries by year in reverse chronological order. -usage: -
      -  $db = zetDB('metrics.bib');
      -  $d = new YearDisplay();
      -  $d->setDB($db);
      -  $d->display();
      -
      -*/ -class YearDisplay { - - /** is an array of strings representing years */ - var $yearIndex; + /** Displays a page bar consisting of clickable page numbers. */ + function displayPageBar($noPages, $page) { - function setDB(&$bibdatabase) { - $this->setEntries($bibdatabase->bibdb); - } + // bug found by benoit, first we have to reset the q_result + $this->filter[Q_RESULT] = 1; - /** creates a YearDisplay */ - function setOptions(&$options) {} + $barSize = 10; // *2 + $start = ($page - $barSize) > 0 ? $page - $barSize : 1; + $end = min($noPages, $start + $barSize * 2); - function getTitle() {return '';} - - /** sets the entries to be shown */ - function setEntries(&$entries) { - $this->entries = $entries; - $db= createBibDataBase(); - $db->bibdb = $entries; - $this->yearIndex = $db->yearIndex(); - } - - /** Displays a set of bibtex entries in an HTML table */ - function display() { - $delegate = createBasicDisplay(); - $delegate->setEntries($this->entries); - $index = count($this->entries); - foreach($this->yearIndex as $year) { - $x = array(); - uasort($x,'compare_bib_entry_by_month'); - foreach($this->entries as $e) { - if ($e->getYear() == $year) { - $x[] = $e; - } - } - - if (count($x)>0) { - echo '
      '.$year.'
      '; - $delegate->setEntries($x); - $delegate->display(); - } - - $index = $index - count($x); + echo ''; } +} - function indexDown() { - $index=count($this->entries); - foreach ($this->entries as $bib) { - $bib->setAbbrv((string)$index--); - } // end foreach - return $this->entries; - } - - function setTitle($title) { $this->title = $title; return $this; } - function getTitle() { return @$this->title ; } - - /** Displays a set of bibtex entries in an HTML table */ - function display() { - - uasort($this->entries, ORDER_FUNCTION); +/** creates an RSS link with text or image depending on the environment */ +function createRSSLink($filter) { + // default label + $label='[rss]'; + // auto adaptive code :-) + //if (is_file('rss.png')) $label=''; + return ''.$label.''; +} - if ($this->options) { - foreach($this->options as $fname=>$opt) { - $this->$fname($opt,$entries); - } + +/** + * Displays the summary information of each bib entries of the + * current page. For each entry, this method displays the author, + * title; the bib entries are displayed grouped by the + * publication years. If the bib list is empty, an error message is + * displayed. + */ +class DefaultContentStrategy { + + /** $display: an instance of PagedDisplay */ + function display(&$display) { + // create a year -> entries map to display by years + $years = array(); + foreach ($display->result as $e) { + $y = trim($e->getField(YEAR)); + $years[$y][$e->getKey()] = $e; + } + krsort($years); + + switch(LAYOUT) { /* MG: added switch for different layouts */ + case 'list': + ?> +
        + +
      +
      menuPageBar($pageKey, $numEntries, $page, $pageSize, $startIndex, $endIndex);?>
      + displayMenuItems($list, $startIndex, $endIndex, $targetKey); ?>
      + +
      + '; - echo 'Order: '.ORDER_FUNCTION.'
      '; - echo 'Abbrv: '.ABBRV_TYPE.'
      '; - echo 'Options: '.@implode(',',$this->options).'
      '; + $index = 0; + $refnum = count($display->result)-(($display->page-1)*PAGE_SIZE); + foreach ($years as $year => $entries) { + + if ($display->isDisplayed($index)) { + switch(LAYOUT) { + case 'deflist': + case 'list': + ?> +
      + +
      + + + isDisplayed($index)) { + $bib->setAbbrv($refnum--); + switch(LAYOUT) { + case 'list': $bib->toLI(); break; + case 'table': $bib->toTR(); break; + case 'deflist': $bib->toDD(); break; + } + } + $index++; + + } // end foreach + } + switch(LAYOUT) { + case 'list': + ?> + + +
      + + + - - - entries); - $i=0; - foreach ($this->entries as $bib) { - // by default, index are in decrasing order - // so that when you add a publicaton recent , the indices of preceding publications don't change - $bib->setIndex('['.($count-($i++)).']'); - $bib->toTR(); - } // end foreach - ?> -
      - - Sorry, this bib entry does not exist. - Back to bibtexbrowser - title = $title; return $this; } - function getTitle() { return @$this->title ; } - function display() { - echo 'no result found, sorry.'; + function NonExistentBibEntryError() { + header('HTTP/1.1 404 Not found'); + ?> + Sorry, this bib entry does not exist. + Back to bibtexbrowser + - $db = zetDB('metrics.bib'); - $d = new AcademicDisplay(); - $d->setDB($db); - $d->display(); - - */ -class AcademicDisplay { - function getTitle() { return $this->title; } - function setTitle($title) { $this->title = $title; return $this; } +/** Class to display the publication records sorted by publication types. */ +class AcademicDisplay extends BibtexBrowserDisplay { - function setDB(&$bibdatabase) { - $this->setEntries($bibdatabase->bibdb); - } - - /** sets the entries to be shown */ - function setEntries(&$entries) { - $this->entries = $entries; + /** the query */ + var $query; + + /** + * $entries: an array of bib entries + * $query: the array representing the query + */ + function AcademicDisplay(&$entries,&$query) { + $this->query=$query; + $this->db=new BibDataBase(); + $this->db->bibdb = $entries; + $this->title = query2title($query); } + /** overrides */ + function formatedHeader() { return '
      '.$this->title.' '.createRSSLink($this->query).'
      ';} + + /** transforms a query to HTML - * $ query is an array (e.g. array(Q_YEAR=>'2005')) + * $ query is an array (e.g. array(Q_TYPE=>'book')) * $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"; - echo ''."\n"; + echo "\n".'
      '.$title.'
      '."\n"; + switch (LAYOUT) { + case 'list': + echo '
        '."\n"; + break; + case 'table': + echo '
      '."\n"; + break; + case 'deflist': + echo '
      '."\n"; + break; + } // by default the abbreviation is incermented over all // searches - - // since we don't know before hand all section, we can not index in decreasing order static $count; if ($count == NULL) { $count = 1; } // init $id = $count; foreach ($entries as $bib) { - $bib->setIndex('['.($id++).']'); - $bib->toTR(); + $bib->setAbbrv($id++); + switch(LAYOUT) { + case 'list': $bib->toLI(); break; + case 'table': $bib->toTR(); break; + case 'deflist': $bib->toDD(); break; + } } // end foreach $count = @$count + count($entries); - echo '
      '; + switch(LAYOUT) { + case 'list': + ?> +
    + + + + + db = createBibDataBase(); - $this->db->bibdb = $this->entries; - - foreach (_DefaultBibliographySections() as $section) { $this->search2html($section['query'],$section['title']); - } + } + + echo $this->poweredby(); + + if (BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT) { + $this->javascript(); + } + } } @@ -2405,36 +2486,24 @@ class AcademicDisplay { -/** displays a single bib entry. -usage: -
    -  $db = zetDB('metrics.bib');
    -  $dis = new BibEntryDisplay($db->getEntryByKey('Schmietendorf2000'));
    -  $dis->display();
    -
    -notes: -- the top-level header (usually <H1>) must be done by the caller. -- this view is optimized for Google Scholar - */ -class BibEntryDisplay { +/** Class to display a single bib entry. + * This view is optimized for Google Scholar + * */ +class BibEntryDisplay extends BibtexBrowserDisplay { /** the bib entry to display */ var $bib; - function BibEntryDisplay($bib=null) { - $this->bib = $bib; - } - - function setEntries(&$entries) { - $this->bib = $entries[0]; + /** Creates an instance with the given bib entry and header. + * It the object is an instance of BibIndexEntry, it may be + * mutated to read the rest of the fields. + */ + function BibEntryDisplay(&$bibentry) { + $this->bib = $bibentry; + $this->title = $this->bib->getTitle().' (bibtex)'; //$this->title = $this->bib->getTitle().' (bibtex)'.$this->bib->getUrlLink(); } - /** returns the title */ - function getTitle() { - return $this->bib->getTitle().' (bibtex)'; - } - /** 2011/10/02: new display, inspired from Tom Zimmermann's home page */ function displayOnSteroids() { $subtitle = '
    by '.$this->bib->getFormattedAuthorsImproved().'
    '; @@ -2459,6 +2528,7 @@ class BibEntryDisplay { echo '
    '; //echo $this->display_old(); echo $this->displayOnSteroids(); + echo $this->poweredby(); echo '
    '; } @@ -2566,7 +2636,7 @@ class BibEntryDisplay { foreach($this->bib->getArrayOfCommaSeparatedAuthors() as $author) { $result[] = array('DC.Creator',$author); } - $result[] = array('DC.Issued',$this->bib->getYear()); + $result[] = array('DC.Date',$this->bib->getYear()); } // --------------------------------- BEGIN METADATA EPRINTS @@ -2643,15 +2713,10 @@ class BibEntryDisplay { // DATABASE MANAGEMENT // ---------------------------------------------------------------------- -/** represents a bibliographic database that contains a set of bibliographic entries. -usage: -
    -$db = new BibDataBase();
    -$db->load('metrics.bib');
    -$query = array('author'=>'martin', 'year'=>2008);
    -foreach ($db->multisearch($query) as $bibentry) { echo $bibentry->getTitle(); }
    -
    -*/ +/** + * Abstraction of bibliographic database to contain a set of + * bibliographic entries and maintain them. + */ class BibDataBase { /** A hash table from keys (e.g. Goody1994) to bib entries (BibEntry instances). */ var $bibdb; @@ -2660,47 +2725,13 @@ class BibDataBase { var $stringdb; /** Creates a new database by parsing bib entries from the given - * file. (backward compatibility) */ + * file. */ function load($filename) { - $this->update($filename); - } - - /** Updates a database (replaces the new bibtex entries by the most recent ones) */ - function update($filename) { - - $empty_array = array(); - $db = createBibDBBuilder(); - $db->setData($empty_array, $this->stringdb); - $db->build($filename); - - $this->stringdb = array_merge($this->stringdb, $db->stringdb); - - $result = $db->builtdb; - - - foreach ($result as $b) { - // new entries: - if (!isset($this->bibdb[$b->getKey()])) { - //echo 'adding...
    '; - $this->bibdb[$b->getKey()] = $b; - } - // update entry - else if (isset($this->bibdb[$b->getKey()]) && ($b->getText() !== $this->bibdb[$b->getKey()]->getText())) { - //echo 'replacing...
    '; - $this->bibdb[$b->getKey()] = $b; - } - } - - // some entries have been removed - foreach ($this->bibdb as $e) { - if (!isset($result[$e->getKey()]) - && $e->filename==$filename // bug reported by Thomas on Dec 4 2012 - ) { - //echo 'deleting...
    '; - unset($this->bibdb[$e->getKey()]); - } - } - + $db = new BibDBBuilder($filename, $this->bibdb, $this->stringdb); + //print_r($parser); + $this->bibdb = $db->builtdb; + $this->stringdb = $db->stringdb; + //print_r($this->stringdb); } /** Creates a new empty database */ @@ -2709,15 +2740,6 @@ class BibDataBase { $this->stringdb = array(); } - /** Returns the $n latest modified bibtex entries/ */ - function getLatestEntries($n) { - $order='compare_bib_entry_by_mtime'; - $array = $this->bibdb; // array passed by value - uasort($array, $order); - $result = array_slice($array,0,$n); - return $result; - } - /** Returns all entries as an array. Each entry is an instance of * class BibEntry. */ function getEntries() { @@ -2757,7 +2779,7 @@ class BibDataBase { foreach ($this->bibdb as $bib) { foreach($bib->getRawAuthors() as $a){ //we use an array because several authors can have the same lastname - @$result[$bib->getLastName($a)][$bib->formatAuthor($a)]++; + @$result[getLastName($a)][$bib->formatAuthor($a)]++; } } ksort($result); @@ -2779,7 +2801,7 @@ class BibDataBase { $result = array(); foreach ($this->bibdb as $bib) { if (!$bib->hasField("keywords")) continue; - $tags =preg_split('/[,;\\/]/', $bib->getField("keywords")); + $tags =preg_split('/[,;]/', $bib->getField("keywords")); foreach($tags as $a){ $ta = trim($a); $result[$ta] = $ta; @@ -2822,17 +2844,31 @@ class BibDataBase { /** Returns an array of bib entries (BibEntry) that satisfy the query * $query is an hash with entry type as key and searched fragment as value + * the returned array is sorted by year */ function multisearch($query) { if (count($query)<1) {return array();} if (isset($query[Q_ALL])) return array_values($this->bibdb); + if (array_key_exists( Q_BIBLIOGRAPHY, $query )) { + $citations = array(); + foreach ($query[Q_BIBLIOGRAPHY] as $key => $value) { + $citations[$key] = $value; + } + } + if (array_key_exists( Q_KEYS, $query )) { + $citations = array(); + foreach ($query[Q_KEYS] as $id => $key) { + $citations[] = $key; + } + } + $result = array(); foreach ($this->bibdb as $bib) { $entryisselected = true; + $akey = $bib->getYear().$bib->getKey(); foreach ($query as $field => $fragment) { - $field = strtolower($field); if ($field==Q_SEARCH) { // we search in the whole bib entry if (!$bib->hasPhrase($fragment)) { @@ -2844,33 +2880,37 @@ 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)) { + else if ($field==Q_BIBLIOGRAPHY) { + if ( !array_key_exists( $bib->getKey(), $citations ) ) { $entryisselected = false; + } else { + $akey = $citations[$bib->getKey()]; } } - else { + else if ($field==Q_KEYS) { + if ( ! in_array( $bib->getKey(), $citations ) ) { + $entryisselected = false; + } + } else { if (!$bib->hasPhrase($fragment, $field)) { $entryisselected = false; } } - - } - if ($entryisselected) { - $result[] = $bib; } - } - - return $result; + if ($entryisselected) $result[$akey] = $bib; + } + + if (array_key_exists( Q_BIBLIOGRAPHY, $query )) { + ksort($result); // a bibliography is sorted in ascending order + } else { + krsort($result); + } + + return $result; } } // end class -/** returns the default CSS of bibtexbrowser */ +/* returns the default embedded CSS of bibtexbrowser */ function bibtexbrowserDefaultCSS() { ?> @@ -2891,13 +2931,7 @@ function bibtexbrowserDefaultCSS() { text-align: right; } -.btb-header { - background-color: #995124; - color: #FFFFFF; - padding: 1px 2px 1px 2px; -} - -.btb-nav-title { +.header { background-color: #995124; color: #FFFFFF; padding: 1px 2px 1px 2px; @@ -2973,37 +3007,27 @@ 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; } .bibentry-abstract { margin:15px; } .bibentry-label { margin-top:15px; } .bibentry-reference { margin-bottom:15px; padding:10px; background: none repeat scroll 0 0 #F5F5F5; border: 1px solid #DDDDDD; } -.btb-nav { text-align: right; } <BODY> and TITLE) -usage: -
    -  $db = zetDB('metrics.bib');
    -  $dis = new BibEntryDisplay($db->getEntryByKey('Schmietendorf2000'));
    -  new HTMLWrapper($dis);
    -
    -*/ +/** A class to wrap contents in an HTML page + withe and TITLE */ class HTMLWrapper { /** * $content: an object with methods display() getRSS() + formatedHeader() getTitle() * $title: title of the page */ @@ -3018,10 +3042,8 @@ echo ' - -getRSS()!='') echo ''; -?> + +getRSS()!='') echo ''; ?> '.strip_tags($content->getTitle()).''; -} - +echo ''.strip_tags($content->getTitle()).''; + // now the CSS echo ''; ?> -" . $content->getTitle() . ""; -} -?> -display(); - echo poweredby(); - - if (BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT) { - javascript(); - } - - -?> +formatedHeader();?> +display();?> - $db = zetDB('metrics.bib'); - $dis = new SimpleDisplay($db); - new NoWrapper($dis); - -*/ +/** NoWrapper calls method display() on the content. */ class NoWrapper { function NoWrapper(&$content) { + @header('Content-type: text/html; charset='.ENCODING); echo $content->display(); } } -/** is used to create an subset of a bibtex file. -usage: -
    -  $db = zetDB('metrics.bib');
    -  $query = array('year'=>2005);
    -  $dis = new BibtexDisplay()->setEntries($db->multisearch($query));
    -  $dis->display();
    -
    -*/ +/** is used to create an subset of a bibtex file */ class BibtexDisplay { - function BibtexDisplay() {} - - function setTitle($title) { $this->title = $title; return $this; } + /** an array of BibEbtry */ + var $results; + + /** the initial query to get the results */ + var $query; - /** sets the entries to be shown */ - function setEntries(&$entries) { - $this->entries = $entries; + function BibtexDisplay(&$results, &$query) { + $this->results=$results; + $this->query=$query; } - function setWrapper($x) { $x->wrapper = 'NoWrapper'; } - function display() { header('Content-type: text/plain; charset='.ENCODING); - echo '% generated by bibtexbrowser '."\n"; - echo '% '.@$this->title."\n"; + echo '% '.query2title($this->query)."\n"; echo '% Encoding: '.ENCODING."\n"; - foreach($this->entries as $bibentry) { echo $bibentry->getText()."\n"; } + foreach($this->results as $bibentry) { echo $bibentry->getText()."\n"; } exit; } } -/** creates paged output, e.g: [[http://localhost/bibtexbrowser/testPagedDisplay.php?page=1]] -usage: -
    -  $_GET['library']=1;
    -  include( 'bibtexbrowser.php' );
    -  $db = zetDB('metrics.bib');
    -  $pd = new PagedDisplay();
    -  $pd->setEntries($db->bibdb);
    -  $pd->display();
    -
    -*/ -class PagedDisplay { - - var $query = array(); - - function PagedDisplay() { - $this->setPage(); - } - - /** sets the entries to be shown */ - function setEntries(&$entries) { - uasort($entries, ORDER_FUNCTION); - $this->entries = array_values($entries); - } - - /** sets $this->page from $_GET, defaults to 1 */ - function setPage() { - $this->page = 1; - if (isset($_GET['page'])) { - $this->page = $_GET['page']; - } - } - - function setQuery($query = array()) { - $this->query = $query; - } - - function getTitle() { - return query2title($this->query). ' - page '.$this->page; - } - - function display() { - $less = false; - - if ($this->page>1) {$less = true;} - - $more = true; - - // computing $more - $index = ($this->page)*PAGE_SIZE; - if (!isset($this->entries[$index])) { - $more = false; - } - - $this->menu($less, $more); - echo ''; - for ($i = 0; $i < PAGE_SIZE; $i++) { - $index = ($this->page-1)*PAGE_SIZE + $i; - if (isset($this->entries[$index])) { - $bib = $this->entries[$index]; - $bib->toTR(); - - } else { - //break; - } - } // end foreach - echo '
    '; - - $this->menu($less, $more); - } - - function menu($less, $more) { - - echo ''; - - $prev = $this->query; - $prev['page'] = $this->page-1; - if ($less == true) { echo 'Prev Page'; } - - if ($less && $more) { echo ' | '; } - - $next = $this->query; - $next['page'] = $this->page+1; - if ($more == true) { echo 'Next Page'; } - echo ''; +/** is used to create an RSS feed */ +class RSSDisplay { - } -} + /** an array of BibEbtry */ + var $results; -/** is used to create an RSS feed. -usage: -
    -  $db = zetDB('metrics.bib');
    -  $query = array('year'=>2005);
    -  $rss = new RSSDisplay();
    -  $entries = $db->getLatestEntries(10);
    -  $rss->setEntries($entries);
    -  $rss->display();
    -
    -*/ -class RSSDisplay { + /** the initial query to get the results */ + var $query; - var $title = 'RSS produced by bibtexbrowser'; - - function RSSDisplay() { - // nothing by default + function RSSDisplay(&$results, &$query) { + $this->results=$results; + $this->query=$query; + $this->title = query2title($query); } - function setTitle($title) { $this->title = $title; return $this; } - /** tries to always output a valid XML/RSS string * based on ENCODING, HTML tags, and the transformations * that happened in latex2html */ @@ -3262,13 +3155,7 @@ class RSSDisplay { return $desc; } - /** sets the entries to be shown */ - function setEntries(&$entries) { - $this->entries = $entries; - } - - function setWrapper($x) { $x->wrapper = 'NoWrapper'; } - + function display() { header('Content-type: application/rss+xml'); echo ''; @@ -3281,10 +3168,10 @@ class RSSDisplay { http:// - bibtexbrowser v20121205 + bibtexbrowser v20111211 entries as $bibentry) { + foreach($this->results as $bibentry) { ?> <?php echo $this->text2rss($bibentry->getTitle());?> @@ -3296,7 +3183,7 @@ class RSSDisplay { echo $this->text2rss(bib2html($bibentry)."\n".$bibentry->getAbstract()); ?> - getKey());?> + getKey());?> @@ -3309,36 +3196,26 @@ class RSSDisplay { -/** is responsible for transforming a query string of $_GET[..] into a publication list. -usage: -
    -  $_GET['library']=1;
    -  @require('bibtexbrowser.php');
    -  // simulating ?bib=metrics.bib&year=2009
    -  $_GET['bib']='metrics.bib';
    -  $_GET['year']='2006';
    -  $x = new Dispatcher();
    -  $x->main();
    -
    -*/ + class Dispatcher { /** this is the query */ var $query = array(); - /** the displayer of selected entries. The default is set in BIBTEXBROWSER_DEFAULT_DISPLAY. + /** this is the result of the querw: an array of BibEbtry */ + var $selectedEntries = array(); + + /** the displayer of selected entries. The default is a paged display. * It could also be an RSSDisplay if the rss keyword is present */ - var $displayer = ''; + var $displayer = 'PagedDisplay'; /** the wrapper of selected entries. The default is an HTML wrapper * It could also be a NoWrapper when you include your pub list in your home page */ var $wrapper = 'HTMLWrapper'; - function Dispatcher() {} - - function main() { + function Dispatcher() { // are we in test mode, or libray mode // then this file is just a library if (isset($_GET['test']) || isset($_GET['library'])) { @@ -3349,12 +3226,12 @@ class Dispatcher { } // first we set the database (load from disk or parse the bibtex file) - if (!isset($_GET[Q_DB])) { setDB(); } + 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) // realpath is required if the path contains sym-linked directories (bug found by Mark Hereld) - if (strtr(realpath(__FILE__),"\\","/")!=strtr(realpath($_SERVER['SCRIPT_FILENAME']),"\\","/")) $this->wrapper=BIBTEXBROWSER_EMBEDDED_WRAPPER; + if (strtr(realpath(__FILE__),"\\","/")!=strtr(realpath($_SERVER['SCRIPT_FILENAME']),"\\","/")) $this->wrapper='NoWrapper'; // first pass, we will exit if we encounter key or menu or academic // other wise we just create the $this->query @@ -3365,8 +3242,6 @@ class Dispatcher { } } - // at this point, we may have a query - if (count($this->query)>0) { // first test for inconsistent queries @@ -3375,52 +3250,11 @@ class Dispatcher { unset($this->query[Q_ALL]); } - $selectedEntries = $_GET[Q_DB]->multisearch($this->query); - - if (count($selectedEntries)==0) { - $this->displayer = 'NotFoundDisplay'; - } - - // default order - uasort($selectedEntries, ORDER_FUNCTION); - $selectedEntries = array_values($selectedEntries); - - //echo '
    ';print_r($selectedEntries);echo '
    '; - - - if ($this->displayer=='') { - $this->displayer = BIBTEXBROWSER_DEFAULT_DISPLAY; - } - } // otherwise the query is left empty - - // do we have a displayer? - if ($this->displayer!='') { + $this->selectedEntries = $_GET[Q_DB]->multisearch($this->query); - $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')) { - $x->setEntries($selectedEntries); - } - - if (method_exists($x,'setTitle')) { - $x->setTitle(query2title($this->query)); - } - - if (method_exists($x,'setQuery')) { - $x->setQuery($this->query); - } - - // should call method display() on $x - new $this->wrapper($x); - - $this->clearQuery(); + // required for PHP4 to have this intermediate variable + $x = new $this->displayer($this->selectedEntries,$this->query); + new $this->wrapper($x); } else { // we send a redirection for having the frameset @@ -3432,20 +3266,10 @@ class Dispatcher { } } - /** clears the query string in $_GET so that bibtexbrowser can be called multiple times */ - function clearQuery() { - $params= array(Q_ALL,'rss', 'astext', Q_SEARCH, Q_EXCLUDE, Q_YEAR, EDITOR, Q_TAG, Q_AUTHOR, Q_TYPE, Q_ACADEMIC, Q_KEY); - foreach($params as $p) { unset($_GET[$p]); } - } - function all() { $this->query[Q_ALL]=1; } - function display() { - $this->displayer=$_GET['display']; - } - function rss() { $this->displayer='RSSDisplay'; $this->wrapper='NoWrapper'; @@ -3463,35 +3287,42 @@ class Dispatcher { $this->query[Q_SEARCH]=$_GET[Q_SEARCH]; } - function exclude() { $this->query[Q_EXCLUDE]=$_GET[Q_EXCLUDE]; } - - function year() { - // we may want the latest - if ($_GET[Q_YEAR]=='latest') { - $years = $_GET[Q_DB]->yearIndex(); - $_GET[Q_YEAR]=array_shift($years); + function bibliography() { + $this->displayer='BibliographyDisplay'; + if (preg_match('/utf-?8/i',ENCODING)) { + $_GET[Q_BIBLIOGRAPHY] = json_decode($_GET[Q_BIBLIOGRAPHY]); } - $this->query[Q_YEAR]=$_GET[Q_YEAR]; + $this->query[Q_BIBLIOGRAPHY]=$_GET[Q_BIBLIOGRAPHY]; } + + function exclude() { $this->query[Q_EXCLUDE]=$_GET[Q_EXCLUDE]; } + + function year() { $this->query[Q_YEAR]=$_GET[Q_YEAR]; } function editor() { $this->query[EDITOR]=$_GET[EDITOR]; } function keywords() { $this->query[Q_TAG]=$_GET[Q_TAG]; } - function author() { + function layout() { print $_GET[LAYOUT]; $this->query[LAYOUT]=$_GET[LAYOUT]; } // added by MG + + function author() { // Friday, October 29 2010 - // 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]; + // 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]; } 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]; } function menu() { - $menu = createMenuManager(); - $menu->setDB($_GET[Q_DB]); + $menu = new MenuManager($_GET[Q_DB]); new $this->wrapper($menu,array(array('robots','noindex'))); return 'END_DISPATCH'; } @@ -3519,27 +3350,26 @@ class Dispatcher { function key() { if ($_GET[Q_DB]->contains($_GET[Q_KEY])) { - $bibentry = $_GET[Q_DB]->getEntryByKey($_GET[Q_KEY]); - $entries = array($bibentry); - if (isset($_GET['astext'])) { - $bibdisplay = new BibtexDisplay(); - $bibdisplay->setEntries($entries); - $bibdisplay->display(); - } else { - $bibdisplay = createBibEntryDisplay(); - $bibdisplay->setEntries($entries); - new $this->wrapper($bibdisplay,$bibdisplay->metadata()); - } + $bibdisplay = new BibEntryDisplay($_GET[Q_DB]->getEntryByKey($_GET[Q_KEY])); + new $this->wrapper($bibdisplay,$bibdisplay->metadata()); return 'END_DISPATCH'; } - else { nonExistentBibEntryError(); } + else { new NonExistentBibEntryError(); } + } + + function keys() { + if (preg_match('/utf-?8/i',ENCODING)) { + // Create array from list of bibtex entries + $_GET[Q_KEYS] = array_filter(explode(',',strtr($_GET[Q_KEYS]," ",",")),'strlen'); + } + $this->query[Q_KEYS]=$_GET[Q_KEYS]; } /** is used to remotely analyzed a situation */ function diagnosis() { header('Content-type: text/plain'); echo "php version: ".phpversion()."\n"; - echo "bibtexbrowser version: 20121205\n"; + echo "bibtexbrowser version: 20111211\n"; echo "dir: ".decoct(fileperms(dirname(__FILE__)))."\n"; echo "bibtex file: ".decoct(fileperms($_GET[Q_FILE]))."\n"; exit; @@ -3551,26 +3381,25 @@ class Dispatcher { - + You are browsing <?php echo $_GET[Q_FILE]; ?> with bibtexbrowser - + main(); -?> \ No newline at end of file +new Dispatcher(); + +?> + diff --git a/bibtexbrowser_bibliography.php b/bibtexbrowser_bibliography.php new file mode 100644 index 0000000..8cdbc30 --- /dev/null +++ b/bibtexbrowser_bibliography.php @@ -0,0 +1,37 @@ +' . $a . '' ; +} + +// Create citations from bibtex entries. One argument per bibtex entry. +/* Example: As shown in , one can cite +*/ +function cite() { + global $citations; + $entries = func_get_args(); // list of bibtex entries + $refs = array(); // corresponding references + foreach ($entries as $entry) { + if ( array_key_exists ( $entry , $citations ) ) { + $ref = $citations[$entry] ; + } else { + $ref = count( $citations ) + 1 ; + $citations[$entry] = $ref ; + } + $refs[] = $ref; + } + sort( $refs ); + $links = array_map( 'linkify', $refs ); + echo "[" . implode(",",$links) . "]" ; +} + +function make_bibtexbrowser_bibliography() { + global $citations; + return json_encode($citations) ; +} + +?> From 29c5be5af9cf863401770022dc8a6374fbb35aa5 Mon Sep 17 00:00:00 2001 From: Matthieu Guillaumin Date: Tue, 26 Feb 2013 23:48:11 +0100 Subject: [PATCH 3/8] merged bibtexbrowser20121205 with bibliography, lists, thumbnails, icons --- bibtexbrowser.local.php | 155 +-- bibtexbrowser.php | 2655 ++++++++++++++++++++++----------------- 2 files changed, 1543 insertions(+), 1267 deletions(-) diff --git a/bibtexbrowser.local.php b/bibtexbrowser.local.php index d949c64..3b45ff3 100644 --- a/bibtexbrowser.local.php +++ b/bibtexbrowser.local.php @@ -123,153 +123,34 @@ function MGBibliographyStyle(&$bibentry) { /** Class to display a bibliography of a page. */ class BibliographyDisplay { - /** the bib entries to display. */ - var $result; - - /** the content strategy (cf. pattern strategy) */ - var $contentStrategy; - - /** the query to reinject in links to different pages */ - var $filter; - - /** Creates an instance with the given entries and header. */ - function BibliographyDisplay(&$result, $filter) { - $this->result = $result; - $this->filter = $filter; - // requesting a different page of the result view? - $this->setTitle(); - $this->contentStrategy = new BibliographyContentStrategy(); + function setDB(&$bibdatabase) { + $this->setEntries($bibdatabase->bibdb); } - /** sets the $this->title of BibtexBrowserDisplay based on the $filter */ - function setTitle() { - $this->title = query2title($this->filter); + /** sets the entries to be shown */ + function setEntries(&$entries) { + $this->entries = $entries; } - /** overrides */ - function formatedHeader() { return '
    '.$this->title.' '.createRSSLink($this->filter).'
    ';} + function setTitle($title) { $this->title = $title; return $this; } + function getTitle() { return @$this->title ; } - /** overrides */ - function getURL() { return '?'.createQueryString($this->filter);} - - /** overrides */ - function getRSS() { return BIBTEXBROWSER_URL.'?'.createQueryString($this->filter).'&rss';} - - /** Displays the entries preceded with the header. */ + /** Displays a set of bibtex entries in an HTML table */ function display() { - // print error message if no entry. - if (empty($this->result)) { - echo "No references.\n"; - return; - } - $this->contentStrategy->display($this); - echo $this->poweredby(); - if (BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT) { - $this->javascript(); - } - } - - function poweredby() { - $poweredby = "\n".'
    '; - $poweredby .= ''; - $poweredby .= 'Powered by bibtexbrowser'; - $poweredby .= '
    '."\n"; - return $poweredby; - } - - /** Adds a touch of AJAX in bibtexbrowser to display bibtex entries inline. - * It uses the HIJAX design pattern: the Javascript code fetches the normal bibtex HTML page - * and extracts the bibtex. - * In other terms, URLs and content are left perfectly optimized for crawlers - * Note how beautiful is this piece of code thanks to JQuery. - */ - function javascript() { - // we use jquery with the official content delivery URLs - // Microsoft and Google also provide jquery with their content delivery networks -?> -entries); //, ORDER_FUNCTION); -} + layoutHeaderHTML(); -class BibliographyContentStrategy { - - /** $display: an instance of PagedDisplay */ - function display(&$display) { - switch(LAYOUT) { /* MG: added switch for different layouts */ - case 'list': - ?> -
      - - - -
      - result; - $refnum = count($display->result); - - foreach ($entries as $value => $bib) { - $bib->setAbbrv($value); - switch(LAYOUT) { - case 'list': $bib->toLI(); break; - case 'table': $bib->toTR(); break; - case 'deflist': $bib->toDD(); break; - } + $count = count($this->entries); + $i=0; + foreach ($this->entries as $ref => $bib) { + $bib->setIndex($ref); + $bib->toHTML(); } // end foreach - - switch(LAYOUT) { - case 'list': - ?> - - -
      - - - - -bibtexbrowser is a PHP script that creates publication lists from Bibtex files. - bibtexbrowser is stable, mature and easy to install. It is used in [[users|60+ different universities]] around the globe. - -+++TOC+++ - -=====Major features===== -* **(11/2009)** bibtexbrowser generates [[http://www.monperrus.net/martin/accurate+bibliographic+metadata+and+google+scholar|Google Scholar metadata]] so as to improve the visibility of your papers on Google Scholar. Since Google has now [[http://scholar.google.com/intl/en/scholar/inclusion.html|documented this feature]], as of version ≥20100621, Google Scholar Metadata should be completely correct. -* **(11/2009)** More and more academics use bibliographic software like [[http://www.zotero.org/|Zotero]] or [[http://www.mendeley.com/|Mendeley]]. bibtexbrowser generates [[http://ocoins.info/|COinS]] for automatic import of bibliographic entries with [[http://www.zotero.org/|Zotero]] and [[http://www.mendeley.com/|Mendeley]]. -* **(10/2009)** People can subscribe to the RSS publication feed of an individual or a group so as to being kept up-to-date: bibtexbrowser generates RSS feeds for all queries (simply add &rss at the end of the URL)! [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=monperrus.bib&all&rss|demo]] -* **(02/2009)** bibtexbrowser can display all entries for an author with an academic style (i.e book, articles, conference, workshop): [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&academic=Ducasse|demo]] -* **(05/2008)**: bibtexbrowser can be used to embed a publication list into another page: [[http://www.monperrus.net/martin/|demo]] -* **(04/2007)**: bibtexbrowser is easy to install: just a single file. - -=====Other features===== -* **(10/2011)** if a bibtex entry contains a field gsid (like Google Scholar ID), bibtexbrowser includes a link [cites] to the cited-by page of Google Scholar (e.g. [[http://scholar.google.com/scholar?cites=15080874515065717592]]) -* **(03/2011)** bibtexbrowser includes a hide/show mechanism for bibtex entries (in Javascript, see configuration variable BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT) -* **(10/2010)** bibtexbrowser now supports cross-references (Bibtex crossref) -* **(09/2010)** bibtexbrowser now supports multiple bibtex files (''bibtexbrowser.php?bib=file1.bib;file2.bib'') -* **(05/2010)** bibtexbrowser adds links to your co-author pages if you define the corresponding @string (see function addHomepageLink) -* **(01/2010)** bibtexbrowser can handle user-defined bibliographic styles -* **(10/2009)** bibtexbrowser is able to generate a bibtex file containing only the selected entries (simply add &astext at the end of the link) -* **(10/2009)** bibtexbrowser is now independent of the configuration of register_globals -* **(01/2009)** bibtexbrowser allows multi criteria search, e.g. [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&type=inproceedings&year=2004|demo]] -* bibtexbrowser replaces constants defined in @STRING -* bibtexbrowser is very fast because it keeps a compiled version of the bibtex file (PHP object serialized) -* bibtexbrowser is compatible with PHP 4.x and PHP 5.x -* bibtexbrowser can display the menu and all entries without filtering from the file name passed as parameter [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib|demo]] -* bibtexbrowser can display all entries out of a bibtex file [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&all|demo]] -* bibtexbrowser can display all entries for a given year [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&year=2004|demo]] -* bibtexbrowser can display a single bibtex entry [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&key=monperrus08d|demo]] -* bibtexbrowser can display found entries with a search word (it can be in any bib field) [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&search=ocl|demo]] -* bibtexbrowser can display all entries with a bib keyword -* bibtexbrowser outputs valid XHTML 1.0 Transitional -* bibtexbrowser can display all entries for an author [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib&author=Barbara+A.+Kitchenham|demo]] -* bibtexbrowser can be used with different encodings (change the default iso-8859-1 encoding if your bib file is in UTF-8 ''define('ENCODING','UTF-8')'' ) - - -=====Download===== -For feature requests, bug reports, or patch proposals, [[http://www.monperrus.net/martin/|please drop me an email ]] or comment this page. Don't hesitate to contact me to be added in the [[users|lists of bibtexbrowser users]] :-) - -You may try bibtexbrowser without installation by uploading your bibtex file at [[http://my.publications.li]]. - -**[[http://www.monperrus.net/martin/bibtexbrowser.php.txt|Download bibtexbrowser]]** (Try the release candidate!)';} ?> - - -=====Demo and screenshot===== - -Demo: [[http://www.monperrus.net/martin/bibtexbrowser.php?bib=metrics.bib|Here, you can browse a bibtex file dedicated to software metrics]] - -bibtexbrowser screenshot - -=====Basic installation===== -
      -Create a bib file with the publication records (e.g. csgroup2008.bib) and upload it to your server. -* Use the link ''bibtexbrowser.php?bib=csgroup2008.bib'' (frameset based view) -* Use the link ''bibtexbrowser.php?bib=csgroup2008.bib&all'' (pub list sorted by year) -* Use the link ''bibtexbrowser.php?bib=csgroup2008.bib&all&academic'' (pub list sorted by publication type, then by year, see "Sectioning in academic mode" below) - -** Warning **: bibtexbrowser maintains a cached version of the parsed bibtex, for high performance, check that PHP can write in the working directory of PHP. - -**Handling mutliple bibtex files**: If you want to include several bibtex files, just give bibtexbrowser the files separated by semi-columns e.g: -''bibtexbrowser.php?bib=strings.bib;csgroup2008.bib'' - -
      - -=====UTF-8 support / ISO-8859-1 support===== - -^^By default, bibtexbrowser assumes that the bibtex file is UTF-8 encoded. -If you want to change it to e.g. ISO-8859-1, add ''define('ENCODING','ISO-8859-1');'' into ''bibtexbrowser.local.php'' (see below). -Note that if the bibtex only contains latex-encoded diacritics (e.g. ''\'e''), it does not matter. -^^ -=====How to embed your publication list in your home page===== -
      - - - - - - - - - - - -
      Sorted by year Sorted by publication type
      For a group/team/lab -<?php -$_GET['bib']='csgroup2008.bib'; -$_GET['all']=1; -include( 'bibtexbrowser.php' ); -?> - -<?php -$_GET['bib']='csgroup2008.bib'; -$_GET['all']=1; -define('ABBRV_TYPE','year'); -$_GET['academic']=1; -include( 'bibtexbrowser.php' ); -?> -
      For an individual - <?php -$_GET['bib']='mybib.bib'; -$_GET['author']='Martin Monperrus'; -include( 'bibtexbrowser.php' ); -?> - -<?php -$_GET['bib']='mybib.bib'; -$_GET['author']='Martin Monperrus'; -define('ABBRV_TYPE','year'); -$_GET['academic']=1; -include( 'bibtexbrowser.php' ); -?> -
      -
      - -=====Sectioning in academic mode===== - -The default academic mode creates four sections : -- books -- articles and book chapters -- workshop papers (for entries containing "workshop" in the field booktitle) -- others. - -You may create your own one in ''bibtexbrowser.local.php'' (see also "By creating a bibtexbrowser.local.php" below): -
      -define('BIBLIOGRAPHYSECTIONS','my_sectioning');
      -function my_sectioning() {
      -return  
      -  array(
      -  // Books
      -    array(
      -      'query' => array(Q_TYPE=>'book'),
      -      'title' => 'Books'
      -    ),
      -  // Articles
      -    array(
      -      'query' => array(Q_TYPE=>'article'),
      -      'title' => 'Refereed Articles'
      -    ),
      -  // Conference and Workshop papers
      -    array(
      -      'query' => array(Q_TYPE=>'inproceedings),
      -      'title' => 'Conference and Workshop  Papers'
      -    ),
      -  // others
      -    array(
      -      'query' => array(Q_TYPE=>'misc|phdthesis|mastersthesis|bachelorsthesis|techreport'),
      -      'title' => 'Other Publications'
      -    )
      -  );
      -}
      -
      - -=====How to tailor bibtexbrowser?===== - -====By modifying the CSS==== -
      - -If bibtexbrowser.css exists, it is used, otherwise bibtexbrowser uses its own embedded CSS style (see function bibtexbrowserDefaultCSS). An example of CSS tailoring is: -
      -.date {   background-color: blue; }
      -.rheader {  font-size: large }
      -.bibref {  padding:3px; padding-left:15px;  vertical-align:top;}
      -.bibtitle { font-weight:bold; }
      -.bibbooktitle { font-style:italic; }
      -
      -
      - -====By modifying the bibliography style ==== -
      -The bibliography style is encapsulated in a function. If you want to modify the bibliography style, you can copy the default style ([[bibtexbrowser-style-default.php.txt|source]]) in a new file, say ''bibtexbrowser-yourstyle.php'', and rename the function ''DefaultBibliographyStyle'' in say ''MyFancyBibliographyStyle''. -Then, add in the file ''bibtexbrowser.local.php'' (see below): - -<?php -include( 'bibtexbrowser-yourstyle.php' ); -define('BIBLIOGRAPHYSTYLE','MyFancyBibliographyStyle'); -?> - - -[[http://www.monperrus.net/martin/bibtexbrowser-style-janos.php.txt|Janos Tapolcai contributed with this style, which looks like IEEE references]]. -For contributing with a new style, [[http://www.monperrus.net/martin/|please drop me an email ]] -
      - -====By creating a bibtexbrowser.local.php==== -
      - -All the variable parts of bibtexbrowser can be modified with a file called ''bibtexbrowser.local.php''. - -
      -<?php
      -// ------------------------------- NOVICE LEVEL
      -// if your bibtex file is UTF-8 encodedd
      -// define("ENCODING","UTF-8");
      -
      -// number of bib items per page
      -// define('PAGE_SIZE',50);
      -
      -// disable Javascript progressive enhancement
      -// define('BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT',false);
      -
      -// may be default/year/x-abbrv
      -// default => [1] The essence of metamodeling
      -// year => [2005] The essence of metamodeling
      -// x-abbrv => [SoSyM] The essence of metamodeling if the bibtex entry contains a field x-abbrv
      -//define('ABBRV_TYPE','default');
      -
      -// see the other define(...) in the source, they are all overridable
      -
      -// ------------------------------- INTERMEDIATE LEVEL
      -
      -// if you are not satisifed with the default style
      -// define('BIBLIOGRAPHYSTYLE','MyFancyBibliographyStyle');
      -function MyFancyBibliographyStyle() {
      -   // see function DefaultBibliographyStyle
      -}
      -
      -// if you are not satisifed with the default sections
      -// define('BIBLIOGRAPHYSECTIONS','mySections');
      -function mySections() {
      -return  
      -  array(
      -  // Books
      -    array(
      -      'query' => array(Q_TYPE=>'book'),
      -      'title' => 'Cool Books'
      -    ),
      -  // .. see function DefaultBibliographySections
      -);
      -}
      -
      -
      -// ------------------------------- EXPERT LEVEL
      -// define('BIBTEXBROWSER_URL','path/to/bibtexbrowser.php'); // if bibtexbrowser.php is in another directory in embedded mode
      -// define('BIBTEXBROWSER_URL',''); // to get the individual bib pages embedded as well
      -
      -?>
      -
      -
      - - - -=====How to add links to the slides of a conference/workshop paper?===== + +URL: http://www.monperrus.net/martin/bibtexbrowser/ +Feedback & Bug Reports: martin.monperrus@gmail.com -You can simply fill the ''comment'' field of the bib entry with an HTML link: - -@inproceedings{foo, -author="Jean Dupont", -title="Bibtexbrowser", -year=2009, -booktitle="Proceedings of the BIB conference", -comment={<a href="myslides.pdf">[slides]</a>} -} - - -This comment field can also be used to add acceptance rates and impact factors. - -=====Related tools===== - -Old-fashioned: -[[http://nxg.me.uk/dist/bibhtml/|bibhtml]], [[http://www.litech.org/~wkiri/bib2html/|bib2html]], [[http://ilab.usc.edu/bibTOhtml/|bibtohtml]], [[http://people.csail.mit.edu/rahimi/bibtex/|bibtextohtml]], [[http://www.lri.fr/~filliatr/bibtex2html/|bibtex2html]], [[http://people.csail.mit.edu/mernst/software/bibtex2web.html |bibtex2web]], [[http://strategoxt.org/Stratego/BibtexTools|stratego bibtex module]] -Unlike them, **bibtexbrowser is dynamic**.i.e.; generates the HTML pages on the fly. Thus, you do not need to regenerate the static HTML files each time the bib file is changed. - -Heavyweight: -[[http://www.rennes.supelec.fr/ren/perso/etotel/PhpBibtexDbMng/|PHP BibTeX Database Manager]], [[http://gforge.inria.fr/projects/bibadmin/|bibadmin]], [[http://artis.imag.fr/Software/Basilic/|basilic]], [[http://phpbibman.sourceforge.net/|phpbibman]], [[http://www.aigaion.nl/|aigaion]], [[http://www.refbase.net/|refbase]], [[http://wikindx.sourceforge.net/|wikindx]], [[http://refdb.sourceforge.net/|refdb]] -Unlike them, **bibtexbrowser does not need a MySQL database** - - -Main competitor: -[[http://code.google.com/p/simplybibtex/|SimplyBibtex]] has the same spirit, but the project seems dead since 2006 - -Misc: -[[http://www.sat.ltu.se/publications/publications.m|This matlab script is similar]] - -=====Copyright===== - -This script is a fork from an excellent script of the University of Texas at El Paso. - -(C) 2006-2011 Martin Monperrus +(C) 2013 Matthieu Guillaumin +(C) 2006-2012 Martin Monperrus (C) 2005-2006 The University of Texas at El Paso / Joel Garcia, Leonardo Ruiz, and Yoonsik Cheon This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as @@ -287,23 +13,26 @@ License, or (at your option) any later version. */ -// Wednesday, June 01 2011: bug found by Carlos Br�s -// it should be possible to include( 'bibtexbrowser.php' ); several times in the same script +// it is be possible to include( 'bibtexbrowser.php' ); several times in the same script +// 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','v20111211'); +define('BIBTEXBROWSER','v20130206'); // *************** 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 @define('ENCODING','UTF-8');//@define('ENCODING','iso-8859-1');//define('ENCODING','windows-1252'); // number of bib items per page -@define('PAGE_SIZE',isset($_GET['nopage'])?10000:25); +// we use the same parameter 'num' as Google +@define('PAGE_SIZE',isset($_GET['num'])?(preg_match('/^\d+$/',$_GET['num'])?$_GET['num']:10000):14); // bibtexbrowser uses a small piece of Javascript to improve the user experience // see http://en.wikipedia.org/wiki/Progressive_enhancement // if you don't like it, you can be disable it by adding in bibtexbrowser.local.php @@ -318,11 +47,40 @@ define('BIBTEXBROWSER','v20111211'); // can we load bibtex files on external servers? @define('BIBTEXBROWSER_LOCAL_BIB_ONLY', true); +// the default view in {SimpleDisplay,AcademicDisplay,RSSDisplay,BibtexDisplay} +@define('BIBTEXBROWSER_DEFAULT_DISPLAY','SimpleDisplay'); + // the target frame of menu links @define('BIBTEXBROWSER_MENU_TARGET','main'); // might be define('BIBTEXBROWSER_MENU_TARGET','_self'); in bibtexbrowser.local.php -@define('ABBRV_TYPE','default');// may be default/year/x-abbrv -@define('LAYOUT','table'); // MG: may be table/list/deflist. defines the HTML rendering options (,
        ,
        , resp.). 'list' only works with 'ABBRV_TYPE'='default'. +@define('ABBRV_TYPE','index');// may be year/x-abbrv/key/none/index + +// 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'); + +// only displaying the n newest entries +@define('BIBTEXBROWSER_NEWEST',5); + +@define('BIBTEXBROWSER_NO_DEFAULT', false); + +// do we add [bibtex] links ? +// suggested by Sascha Schnepp +@define('BIBTEXBROWSER_BIBTEX_LINKS',true); + +// should authors be linked to [none/homepage/resultpage] +// none: nothing +// their homepage if defined as @strings +// their publication lists according to this bibtex +@define('BIBTEXBROWSER_AUTHOR_LINKS','homepage'); + +@define('BIBTEXBROWSER_DEBUG',false); @define('COMMA_NAMES',false);// do have authors in a comma separated form? @define('TYPES_SIZE',10); // number of entry types per table @@ -337,18 +95,19 @@ define('BIBTEXBROWSER','v20111211'); @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'); @define('Q_KEY', 'key'); -@define('Q_KEYS', 'keys'); +@define('Q_KEYS', 'keys'); // select entries using a list of bibtex entries @define('Q_SEARCH', 'search'); -@define('Q_BIBLIOGRAPHY', 'bibliography'); +@define('Q_BIBLIOGRAPHY', 'bibliography'); // select entries and their index using a JSON associative array @define('Q_EXCLUDE', 'exclude'); @define('Q_RESULT', 'result'); @define('Q_ACADEMIC', 'academic'); @define('Q_DB', 'bibdb'); +@define('Q_LATEST', 'latest'); @define('AUTHOR', 'author'); @define('EDITOR', 'editor'); @define('SCHOOL', 'school'); @@ -361,6 +120,8 @@ define('BIBTEXBROWSER','v20111211'); @define('METADATA_DC',true); @define('METADATA_EPRINTS',false); +@define('LAYOUT','table'); // may be table/list/deflist. defines the HTML rendering options (
      ,
        ,
        , resp.). 'list' only works with 'ABBRV_TYPE'='index'. + // in embedded mode, we still need a URL for displaying bibtex entries alone // this is usually resolved to bibtexbrowser.php // but can be overridden in bibtexbrowser.local.php @@ -369,6 +130,9 @@ define('BIBTEXBROWSER','v20111211'); // *************** 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 @@ -378,25 +142,32 @@ define('BIBTEXBROWSER','v20111211'); // we ensure that the pages won't get polluted // if future versions of PHP change warning mechanisms... + @error_reporting(E_ERROR); -/** sets the database of bibtex entries (object of type BibDataBase) - * in $_GET[Q_DB] - * Uses a caching mechanism on disk for sake of performance +/** parses $_GET[Q_FILE] and puts the result (an object of type BibDataBase) in $_GET[Q_DB]. +See also zetDB(). */ function setDB() { + list($db, $parsed, $updated, $saved) = _zetDB(@$_GET[Q_FILE]); + $_GET[Q_DB] = $db; + return $updated; +} + +/** parses the $bibtex_filenames (usually semi-column separated) and returns an object of type BibDataBase. +See also setDB() +*/ +function zetDB($bibtex_filenames) { + list($db, $parsed, $updated, $saved) = _zetDB($bibtex_filenames); + return $db; +} + +/** @nodoc */ +function default_message() { + + if (BIBTEXBROWSER_NO_DEFAULT) { return; } - // Check if magic_quotes_runtime is active - if(get_magic_quotes_runtime()) - { - // Deactivate - // otherwise it does not work - set_magic_quotes_runtime(false); - } - - // default bib file, if no file is specified in the query string. - if (!isset($_GET[Q_FILE]) || $_GET[Q_FILE] == "") { ?>
        Congratulations! bibtexbrowser is correctly installed!
        @@ -404,19 +175,36 @@ function setDB() { You may browse:
        '.$bibfile.'
        '; + $url="?bib=".$bibfile; echo ''.$bibfile.'
        '; } echo "
        "; - return; // we cannot set the db wtihout a bibfile +} + +/** @nodoc */ +function _zetDB($bibtex_filenames) { + + $db = null; + // Check if magic_quotes_runtime is active + if(get_magic_quotes_runtime()) + { + // Deactivate + // otherwise it does not work + set_magic_quotes_runtime(false); + } + + // default bib file, if no file is specified in the query string. + if (!isset($bibtex_filenames) || $bibtex_filenames == "") { + default_message(); + exit; } // first does the bibfiles exist: - // $_GET[Q_FILE] can be urlencoded for instance if they contain slashes + // $bibtex_filenames can be urlencoded for instance if they contain slashes // so we decode it - $_GET[Q_FILE] = urldecode($_GET[Q_FILE]); + $bibtex_filenames = urldecode($bibtex_filenames); // ---------------------------- HANDLING unexistent files - foreach(explode(MULTIPLE_BIB_SEPARATOR, $_GET[Q_FILE]) as $bib) { + foreach(explode(MULTIPLE_BIB_SEPARATOR, $bibtex_filenames) as $bib) { // this is a security protection if (BIBTEXBROWSER_LOCAL_BIB_ONLY && !file_exists($bib)) { @@ -433,7 +221,7 @@ function setDB() { // save bandwidth and server cpu // (imagine the number of requests from search engine bots...) $bib_is_unmodified = isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) ; - foreach(explode(MULTIPLE_BIB_SEPARATOR, $_GET[Q_FILE]) as $bib) { + foreach(explode(MULTIPLE_BIB_SEPARATOR, $bibtex_filenames) as $bib) { $bib_is_unmodified = $bib_is_unmodified && (strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE'])>filemtime($bib)); @@ -448,270 +236,341 @@ function setDB() { // ---------------------------- HANDLING caching of compiled bibtex files // for sake of performance, once the bibtex file is parsed // we try to save a "compiled" in a txt file - $compiledbib = 'bibtexbrowser_'.md5($_GET[Q_FILE]).'.dat'; + $compiledbib = 'bibtexbrowser_'.md5($bibtex_filenames).'.dat'; - $parse=false; - foreach(explode(MULTIPLE_BIB_SEPARATOR, $_GET[Q_FILE]) as $bib) { + $parse=filemtime(__FILE__)>@filemtime($compiledbib); + // do we have a compiled version ? - if (is_file($compiledbib) && is_readable($compiledbib)) { - // is it up to date ? wrt to the bib file and the script - // then upgrading with a new version of bibtexbrowser triggers a new compilation of the bib file - if (filemtime($bib)0 + ) { + $f = fopen($compiledbib,'r+'); + //we use a lock to avoid that a call to bibbtexbrowser made while we write the object loads an incorrect object + if (flock($f,LOCK_EX)) { + $s = filesize($compiledbib); + $ser = fread($f,$s); + $db = @unserialize($ser); + flock($f,LOCK_UN); + } else { die("could not get the lock for reading $compiledbib"); } + fclose($f); + // basic test + // do we have an correct version of the file + if (!is_a($db,'BibDataBase')) { + unlink($compiledbib); + if (BIBTEXBROWSER_DEBUG) { die('$db not a BibDataBase. please reload.'); } + $parse=true; + } } else {$parse=true;} - } // end for each // we don't have a compiled version if ($parse) { //echo ''; // then parsing the file - $db = new BibDataBase(); - foreach(explode(MULTIPLE_BIB_SEPARATOR, $_GET[Q_FILE]) as $bib) { + $db = createBibDataBase(); + foreach(explode(MULTIPLE_BIB_SEPARATOR, $bibtex_filenames) as $bib) { $db->load($bib); } - $_GET[Q_DB]=$db; - - // are we able to save the compiled version ? - // note that the compiled version is saved in the current working directory - if ((!is_file($compiledbib) && is_writable(getcwd())) || (is_file($compiledbib) && is_writable($compiledbib)) ) { - // we can use file_put_contents - // but don't do it for compatibility with PHP 4.3 - $f = fopen($compiledbib,'w'); - //we use a lock to avoid that a call to bbtexbrowser made while we write the object loads an incorrect object - if (flock($f,LOCK_EX)) fwrite($f,serialize($_GET[Q_DB])); - fclose($f); - } - //else echo ''; - } // end parsing and saving + } + + $updated = false; + // now we may update the database + if (!file_exists($compiledbib)) { + @touch($compiledbib); + $updated = true; // limit case + } else foreach(explode(MULTIPLE_BIB_SEPARATOR, $bibtex_filenames) as $bib) { + // is it up to date ? wrt to the bib file and the script + // then upgrading with a new version of bibtexbrowser triggers a new compilation of the bib file + if (filemtime($bib)>filemtime($compiledbib) || filemtime(__FILE__)>filemtime($compiledbib)) { +// echo "updating ".$bib; + $db->update($bib); + $updated = true; + } + } + +// echo var_export($parse); +// echo var_export($updated); + + $saved = false; + // are we able to save the compiled version ? + // note that the compiled version is saved in the current working directory + if ( ($parse || $updated ) && is_writable($compiledbib)) { + // we use 'a' because the file is not locked between fopen and flock + $f = fopen($compiledbib,'a'); + //we use a lock to avoid that a call to bibbtexbrowser made while we write the object loads an incorrect object + if (flock($f,LOCK_EX)) { +// echo ''; + ftruncate($f,0); + fwrite($f,serialize($db)); + flock($f,LOCK_UN); + $saved = true; + } else { die("could not get the lock for writing $compiledbib"); } + fclose($f); + } // end saving the cached verions + //else echo ''; - return $parse; -} // end function setDB + return array(&$db, $parse, $updated, $saved); +} // end function setDB +// factories +// may be overridden in bibtexbrowser.local.php +if (!function_exists('createBibDataBase')) { + /** factory method for openness @nodoc */ + function createBibDataBase() { $x = new BibDataBase(); return $x;} +} +if (!function_exists('createBibEntry')) { + /** factory method for openness @nodoc */ + function createBibEntry() { $x = new BibEntry(); return $x;} +} +if (!function_exists('createBibDBBuilder')) { + /** factory method for openness @nodoc */ + function createBibDBBuilder() { $x = new BibDBBuilder(); return $x;} +} +if (!function_exists('createBasicDisplay')) { + /** factory method for openness @nodoc */ + function createBasicDisplay() { $x = new SimpleDisplay(); return $x;} +} +if (!function_exists('createBibEntryDisplay')) { + /** factory method for openness @nodoc */ + function createBibEntryDisplay() { $x = new BibEntryDisplay(); return $x;} +} +if (!function_exists('createMenuManager')) { + /** factory method for openness @nodoc */ + function createMenuManager() { $x = new MenuManager(); return $x;} +} //////////////////////////////////////////////////////// -/** This class is a generic parser of bibtex files - * It has no dependencies, i.e. it can be used outside of bibtexbrowser - * To use it, simply instantiate it and pass it an object that will receive semantic events - * The delegate is expected to have some methods - * see classes BibDBBuilder and XMLPrettyPrinter +/** is a generic parser of bibtex files. +usage: +
        +  $delegate = new XMLPrettyPrinter();// or another delegate such as BibDBBuilder
        +  $parser = new StateBasedBibtexParser($delegate);
        +  $parser->parse('foo.bib');
        +
        +notes: + - It has no dependencies, it can be used outside of bibtexbrowser + - The delegate is expected to have some methods, see classes BibDBBuilder and XMLPrettyPrinter */ class StateBasedBibtexParser { + + var $delegate; + + function StateBasedBibtexParser(&$delegate) { + $this->delegate = &$delegate; + } + + function parse($bibfilename) { + $delegate = &$this->delegate; + // STATE DEFINITIONS + @define('NOTHING',1); + @define('GETTYPE',2); + @define('GETKEY',3); + @define('GETVALUE',4); + @define('GETVALUEDELIMITEDBYQUOTES',5); + @define('GETVALUEDELIMITEDBYQUOTES_ESCAPED',6); + @define('GETVALUEDELIMITEDBYCURLYBRACKETS',7); + @define('GETVALUEDELIMITEDBYCURLYBRACKETS_ESCAPED',8); + @define('GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL',9); + @define('GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL_ESCAPED',10); + @define('GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL',11); + @define('GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL_ESCAPED',12); + @define('GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL',13); + @define('GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED',14); + + + $state=NOTHING; + $entrytype=''; + $entrykey=''; + $entryvalue=''; + $finalkey=''; + $entrysource=''; + + // metastate + $isinentry = false; + + $delegate->beginFile(); + + $handle = fopen($bibfilename, "r"); + if (!$handle) die ('cannot open '.$bibfilename); + // if you encounter this error "Allowed memory size of xxxxx bytes exhausted" + // then decrease the size of the temp buffer below + $bufsize=BUFFERSIZE; + while (!feof($handle)) { + $sread=fread($handle,$bufsize); + //foreach(str_split($sread) as $s) { + for ( $i=0; $i < strlen( $sread ); $i++) { $s=$sread[$i]; + + if ($isinentry) $entrysource.=$s; + + if ($state==NOTHING) { + // this is the beginning of an entry + if ($s=='@') { + $delegate->beginEntry(); + $state = GETTYPE; + $isinentry = true; + $entrysource='@'; + } + } -function StateBasedBibtexParser($bibfilename, &$delegate) { - - -// STATE DEFINITIONS -@define('NOTHING',1); -@define('GETTYPE',2); -@define('GETKEY',3); -@define('GETVALUE',4); -@define('GETVALUEDELIMITEDBYQUOTES',5); -@define('GETVALUEDELIMITEDBYQUOTES_ESCAPED',6); -@define('GETVALUEDELIMITEDBYCURLYBRACKETS',7); -@define('GETVALUEDELIMITEDBYCURLYBRACKETS_ESCAPED',8); -@define('GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL',9); -@define('GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL_ESCAPED',10); -@define('GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL',11); -@define('GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL_ESCAPED',12); -@define('GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL',13); -@define('GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED',14); - - -$state=NOTHING; -$entrytype=''; -$entrykey=''; -$entryvalue=''; -$finalkey=''; -$entrysource=''; - -// metastate -$isinentry = false; - -$delegate->beginFile(); - -$handle = fopen($bibfilename, "r"); -if (!$handle) die ('cannot open '.$bibfilename); -// if you encounter this error "Allowed memory size of xxxxx bytes exhausted" -// then decrease the size of the temp buffer below -$bufsize=BUFFERSIZE; -while (!feof($handle)) { -$sread=fread($handle,$bufsize); -//foreach(str_split($sread) as $s) { -for ( $i=0; $i < strlen( $sread ); $i++) { $s=$sread[$i]; - - if ($isinentry) $entrysource.=$s; - - if ($state==NOTHING) { - // this is the beginning of an entry - if ($s=='@') { - $delegate->beginEntry(); - $state = GETTYPE; - $isinentry = true; - $entrysource='@'; - } - } + else if ($state==GETTYPE) { + // this is the beginning of a key + if ($s=='{') { + $state = GETKEY; + $delegate->setEntryType($entrytype); + $entrytype=''; + } + else $entrytype=$entrytype.$s; + } + + else if ($state==GETKEY) { + // now we get the value + if ($s=='=') { + $state = GETVALUE; + $finalkey=$entrykey; + $entrykey='';} + // oups we only have the key :-) anyway + else if ($s=='}') { + $state = NOTHING;$isinentry = false;$delegate->endEntry($entrysource); + $entrykey=''; + } + // OK now we look for values + else if ($s==',') { + $state=GETKEY; + $delegate->setEntryKey($entrykey); + $entrykey='';} + else { $entrykey=$entrykey.$s; } + } + // we just got a =, we can now receive the value, but we don't now whether the value + // is delimited by curly brackets, double quotes or nothing + else if ($state==GETVALUE) { - else if ($state==GETTYPE) { - // this is the beginning of a key - if ($s=='{') { - $state = GETKEY; - $delegate->setEntryType($entrytype); - $entrytype=''; - } - else $entrytype=$entrytype.$s; - } + // the value is delimited by double quotes + if ($s=='"') { + $state = GETVALUEDELIMITEDBYQUOTES; + } + // the value is delimited by curly brackets + else if ($s=='{') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS; + } + // the end of the key and no value found: it is the bibtex key e.g. \cite{Descartes1637} + else if ($s==',') { + $state = GETKEY; + $delegate->setEntryField(trim($finalkey),$entryvalue); + $entryvalue=''; // resetting the value buffer + } + // this is the end of the value AND of the entry + else if ($s=='}') { + $state = NOTHING; + $delegate->setEntryField(trim($finalkey),$entryvalue); + $isinentry = false;$delegate->endEntry($entrysource); + $entryvalue=''; // resetting the value buffer + } + else if ($s==' ' || $s=="\t" || $s=="\n" || $s=="\r" ) { + // blank characters are not taken into account when values are not in quotes or curly brackets + } + else { $entryvalue=$entryvalue.$s;} + } - else if ($state==GETKEY) { - // now we get the value - if ($s=='=') { - $state = GETVALUE; - $finalkey=$entrykey; - $entrykey='';} - // oups we only have the key :-) anyway - else if ($s=='}') { - $state = NOTHING;$isinentry = false;$delegate->endEntry($entrysource); - $entrykey=''; - } - // OK now we look for values - else if ($s==',') { - $state=GETKEY; - $delegate->setEntryKey($entrykey); - $entrykey='';} - else { $entrykey=$entrykey.$s; } - } - // we just got a =, we can now receive the value, but we don't now whether the value - // is delimited by curly brackets, double quotes or nothing - else if ($state==GETVALUE) { - - // the value is delimited by double quotes - if ($s=='"') { - $state = GETVALUEDELIMITEDBYQUOTES; - } - // the value is delimited by curly brackets - else if ($s=='{') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS; - } - // the end of the key and no value found: it is the bibtex key e.g. \cite{Descartes1637} - else if ($s==',') { - $state = GETKEY; - $delegate->setEntryField(trim($finalkey),$entryvalue); - $entryvalue=''; // resetting the value buffer - } - // this is the end of the value AND of the entry - else if ($s=='}') { - $state = NOTHING; - $delegate->setEntryField(trim($finalkey),$entryvalue); - $isinentry = false;$delegate->endEntry($entrysource); - $entryvalue=''; // resetting the value buffer - } - else if ($s==' ' || $s=="\t" || $s=="\n" || $s=="\r" ) { - // blank characters are not taken into account when values are not in quotes or curly brackets - } - else { $entryvalue=$entryvalue.$s;} - } - - -/* GETVALUEDELIMITEDBYCURLYBRACKETS* handle entries delimited by curly brackets and the possible nested curly brackets */ - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS) { - - if ($s=='\\') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_ESCAPED; - $entryvalue=$entryvalue.$s;} - else if ($s=='{') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL;$entryvalue=$entryvalue.$s;} - else if ($s=='}') { - $state = GETVALUE;} - else { $entryvalue=$entryvalue.$s;} - } - // handle anti-slashed brackets - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_ESCAPED) { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS; - $entryvalue=$entryvalue.$s; - } - // in first level of curly bracket - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL) { - if ($s=='\\') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL_ESCAPED; - $entryvalue=$entryvalue.$s;} - else if ($s=='{') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL;$entryvalue=$entryvalue.$s;} - else if ($s=='}') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS;$entryvalue=$entryvalue.$s;} - else { $entryvalue=$entryvalue.$s;} - } - // handle anti-slashed brackets - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL_ESCAPED) { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL; - $entryvalue=$entryvalue.$s; - } - - // in second level of curly bracket - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL) { - if ($s=='\\') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL_ESCAPED; - $entryvalue=$entryvalue.$s;} - else if ($s=='{') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL;$entryvalue=$entryvalue.$s;} - else if ($s=='}') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL;$entryvalue=$entryvalue.$s;} - else { $entryvalue=$entryvalue.$s;} - } - // handle anti-slashed brackets - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL_ESCAPED) { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL; - $entryvalue=$entryvalue.$s; - } - - // in third level of curly bracket - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL) { - if ($s=='\\') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED; - $entryvalue=$entryvalue.$s;} - else if ($s=='}') { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL;$entryvalue=$entryvalue.$s;} - else { $entryvalue=$entryvalue.$s;} - } - // handle anti-slashed brackets - else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED) { - $state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL; - $entryvalue=$entryvalue.$s; - } -/* handles entries delimited by double quotes */ - else if ($state==GETVALUEDELIMITEDBYQUOTES) { + /* GETVALUEDELIMITEDBYCURLYBRACKETS* handle entries delimited by curly brackets and the possible nested curly brackets */ + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS) { - if ($s=='\\') { - $state = GETVALUEDELIMITEDBYQUOTES_ESCAPED; - $entryvalue=$entryvalue.$s;} - else if ($s=='"') { - $state = GETVALUE; - } - else { $entryvalue=$entryvalue.$s;} - } - // handle anti-double quotes - else if ($state==GETVALUEDELIMITEDBYQUOTES_ESCAPED) { - $state = GETVALUEDELIMITEDBYQUOTES; - $entryvalue=$entryvalue.$s; - } + if ($s=='\\') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_ESCAPED; + $entryvalue=$entryvalue.$s;} + else if ($s=='{') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL;$entryvalue=$entryvalue.$s;} + else if ($s=='}') { + $state = GETVALUE;} + else { $entryvalue=$entryvalue.$s;} + } + // handle anti-slashed brackets + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_ESCAPED) { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS; + $entryvalue=$entryvalue.$s; + } + // in first level of curly bracket + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL) { + if ($s=='\\') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL_ESCAPED; + $entryvalue=$entryvalue.$s;} + else if ($s=='{') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL;$entryvalue=$entryvalue.$s;} + else if ($s=='}') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS;$entryvalue=$entryvalue.$s;} + else { $entryvalue=$entryvalue.$s;} + } + // handle anti-slashed brackets + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL_ESCAPED) { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL; + $entryvalue=$entryvalue.$s; + } -} // end for -} // end while -$delegate->endFile(); -fclose($handle); -} // end function + // in second level of curly bracket + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL) { + if ($s=='\\') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL_ESCAPED; + $entryvalue=$entryvalue.$s;} + else if ($s=='{') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL;$entryvalue=$entryvalue.$s;} + else if ($s=='}') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_1NESTEDLEVEL;$entryvalue=$entryvalue.$s;} + else { $entryvalue=$entryvalue.$s;} + } + // handle anti-slashed brackets + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL_ESCAPED) { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL; + $entryvalue=$entryvalue.$s; + } + + // in third level of curly bracket + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL) { + if ($s=='\\') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED; + $entryvalue=$entryvalue.$s;} + else if ($s=='}') { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_2NESTEDLEVEL;$entryvalue=$entryvalue.$s;} + else { $entryvalue=$entryvalue.$s;} + } + // handle anti-slashed brackets + else if ($state==GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL_ESCAPED) { + $state = GETVALUEDELIMITEDBYCURLYBRACKETS_3NESTEDLEVEL; + $entryvalue=$entryvalue.$s; + } + + /* handles entries delimited by double quotes */ + else if ($state==GETVALUEDELIMITEDBYQUOTES) { + + if ($s=='\\') { + $state = GETVALUEDELIMITEDBYQUOTES_ESCAPED; + $entryvalue=$entryvalue.$s;} + else if ($s=='"') { + $state = GETVALUE; + } + else { $entryvalue=$entryvalue.$s;} + } + // handle anti-double quotes + else if ($state==GETVALUEDELIMITEDBYQUOTES_ESCAPED) { + $state = GETVALUEDELIMITEDBYQUOTES; + $entryvalue=$entryvalue.$s; + } + + } // end for + } // end while + $delegate->endFile(); + fclose($handle); + //$d = &$this->delegate;print_r($d); + } // end function } // end class -/** This class can be used together with StateBasedBibParser */ +/** is a delegate for StateBasedBibParser. +usage: +see snippet of [[#StateBasedBibParser]] +*/ class XMLPrettyPrinter { function beginFile() { header('Content-type: text/xml;'); @@ -744,23 +603,49 @@ class XMLPrettyPrinter { } } // end class XMLPrettyPrinter -/** This class can be used together with StateBasedBibParser */ +/** builds arrays of BibEntry objects from a bibtex file. +usage: +
        +  $empty_array = array();
        +  $db = new BibDBBuilder(); // see also factory method createBibDBBuilder
        +  $db->build('foo.bib'); // parses foo.bib
        +  print_r($db->builtdb);// an associated array key -> BibEntry objects
        +  print_r($db->stringdb);// an associated array key -> strings representing @string
        +
        +notes: + method build can be used several times, bibtex entries are accumulated in the builder +*/ class BibDBBuilder { /** A hashtable from keys to bib entries (BibEntry). */ - var $builtdb; + var $builtdb = array(); /** A hashtable of constant strings */ - var $stringdb; + var $stringdb = array(); + + var $filename; var $currentEntry; - function BibDBBuilder($filename, &$builtdb, &$stringdb) { + function setData(&$builtdb, &$stringdb) { $this->builtdb = $builtdb; $this->stringdb = $stringdb; - new StateBasedBibtexParser($filename, $this); + return $this; } + function build($filename) { + $this->filename = $filename; + $parser = new StateBasedBibtexParser($this); + $parser->parse($filename); + //print_r(array_keys(&$this->builtdb)); + //print_r(&$this->builtdb); + } + + + function getBuiltDb() { + //print_r($this->builtdb); + return $this->builtdb; + } function beginFile() { } @@ -784,6 +669,7 @@ class BibDBBuilder { } } } + //print_r($this->builtdb); } function setEntryField($finalkey,$entryvalue) { @@ -822,18 +708,27 @@ class BibDBBuilder { } function beginEntry() { - $this->currentEntry = new BibEntry(); + $this->currentEntry = createBibEntry(); + $this->currentEntry->setFile($this->filename); } function endEntry($entrysource) { - // we can set the fulltext + // 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 @@ -844,13 +739,13 @@ 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; } } // we add it to the database else { - $this->builtdb[$this->currentEntry->getKey()] = $this->currentEntry; + $this->builtdb[$this->currentEntry->getKey()] = $this->currentEntry; } } } // end class BibDBBuilder @@ -858,8 +753,7 @@ class BibDBBuilder { -/** extended version of the trim function - * removes linebreaks, tabs, etc. +/** is an extended version of the trim function, removes linebreaks, tabs, etc. */ function xtrim($line) { $line = trim($line); @@ -877,22 +771,25 @@ function xtrim($line) { return $line; } -/** encapsulates the conversion of a single latex chars to the corresponding HTML entity - * this works thanks to the regularity of html entities - * it expects a **lower** char - */ +/** encapsulates the conversion of a single latex chars to the corresponding HTML entity. +It expects a **lower-case** char. +*/ function char2html($line,$latexmodifier,$char,$entitiyfragment) { - $line = str_replace('\\'.$latexmodifier.$char,'&'.$char.''.$entitiyfragment.';', $line); - $line = str_replace('\\'.$latexmodifier.'{'.$char.'}','&'.$char.''.$entitiyfragment.';', $line); - $line = str_replace('\\'.$latexmodifier.strtoupper($char),'&'.strtoupper($char).''.$entitiyfragment.';', $line); - $line = str_replace('\\'.$latexmodifier.'{'.strtoupper($char).'}','&'.strtoupper($char).''.$entitiyfragment.';', $line); + $line = char2html_case_sensitive($line,$latexmodifier,strtoupper($char),$entitiyfragment); + return char2html_case_sensitive($line,$latexmodifier,strtolower($char),$entitiyfragment); +} + +function char2html_case_sensitive($line,$latexmodifier,$char,$entitiyfragment) { +// old version +// $line = str_replace('\\'.$latexmodifier.$char,'&'.$char.''.$entitiyfragment.';', $line); +// $line = str_replace('\\'.$latexmodifier.' '.$char,'&'.$char.''.$entitiyfragment.';', $line); +// $line = str_replace('\\'.$latexmodifier.'{'.$char.'}','&'.$char.''.$entitiyfragment.';', $line); + $line = preg_replace('/\\\\'.preg_quote($latexmodifier,'/').' ?\\{?'.$char.'\\}?/','&'.$char.''.$entitiyfragment.';', $line); return $line; } -/** converts latex chars to HTML entities - * it uses a naive algortihm - * I still look for a comprehensive translation table from late chars to html - * just have this http://isdc.unige.ch/Newsletter/help.html +/** converts latex chars to HTML entities. +(I still look for a comprehensive translation table from late chars to html, better than [[http://isdc.unige.ch/Newsletter/help.html]]) */ function latex2html($line) { $line = preg_replace('/([^\\\\])~/','\\1 ', $line); @@ -951,6 +848,7 @@ function latex2html($line) { $line = char2html($line,'.','a',"ring"); $line = char2html($line,'c','c',"cedil"); + $line = char2html($line,'v','s',"caron"); $line = str_replace('\\ae','æ', $line); $line = str_replace('\\ss','ß', $line); @@ -967,10 +865,14 @@ function latex2html($line) { return $line; } -/** Note that & are encoded as %26 and not as & so it does not break the Z3988 URL */ +/** encodes strings for Z3988 URLs. Note that & are encoded as %26 and not as &. */ function s3988($s) {return urlencode(utf8_encode($s));} -/** @deprecated */ +/** +see BibEntry->formatAuthor($author) +@deprecated +@nodoc +*/ function formatAuthor() { die('Sorry, this function does not exist anymore, however, you can simply use $bibentry->formatAuthor($author) instead.'); } @@ -979,9 +881,16 @@ function formatAuthor() { // BIB ENTRIES // ---------------------------------------------------------------------- -/** - * Class to represent a bibliographic entry. - */ +/** represents a bibliographic entry. +usage: +
        +  $db = zetDB('metrics.bib');
        +  $entry = $db->getEntryByKey('Schmietendorf2000');
        +  echo bib2html($entry);
        +
        +notes: +- BibEntry are usually obtained with getEntryByKey or multisearch +*/ class BibEntry { /** The fields (fieldName -> value) of this bib entry. */ @@ -996,6 +905,23 @@ class BibEntry { /** The verbatim copy (i.e., whole text) of this bib entry. */ var $text; + /** A timestamp to trace when entries have been created */ + var $timestamp; + + /** The name of the file containing this entry */ + var $filename; + + /** The short name of the entry (parameterized by ABBRV_TYPE) */ + var $abbrv; + + /** The index in a list of publications (e.g. [1] Foo */ + var $index = ''; + + /** returns a debug string representation */ + function __toString() { + return $this->getType()." ".$this->getKey(); + } + /** Creates an empty new bib entry. Each bib entry is assigned a unique * identification number. */ function BibEntry() { @@ -1004,17 +930,30 @@ class BibEntry { $this->text =''; } + /** Sets the name of the file containing this entry */ + function setFile($filename) { + $this->filename = $filename; + return $this; + } + + /** Adds timestamp to this object */ + function setTimestamp() { + $this->timestamp = time(); + } + /** Returns the timestamp of this object */ + function getTimestamp() { + return $this->timestamp; + } + /** 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); - // by default the ID is the key - $this->id = $value; + $this->setField(Q_KEY,$value); } /** Sets a field of this bib entry. */ @@ -1040,8 +979,10 @@ 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; } /** Tries to build a good URL for this entry */ function getURL() { @@ -1049,7 +990,9 @@ class BibEntry { $f = BIBTEXBROWSER_URL_BUILDER; return $f($this); } - return BIBTEXBROWSER_URL.'?'.createQueryString(array('key'=>$this->getKey())); +// echo $this->filename; +// echo $this->getKey(); + return BIBTEXBROWSER_URL.'?'.createQueryString(array(Q_KEY=>$this->getKey(), Q_FILE=>$this->filename)); } /** Tries to build a good absolute URL for this entry */ @@ -1061,38 +1004,37 @@ class BibEntry { return "http://".$_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME']).'/'.$this->getURL(); } - /** MG: replace [$ext] with an icon whose url is defined in a string - * e.g. getIconOrTxt('pdf') will show the icon defined by @string{icon_pdf="http://mywebsite/pdf.png"} or print '[pdf]' - * or getIconOrTxt('pdf','paper') will show the icon defined by @string{icon_pdf="http://mywebsite/pdf.png"} or print '[paper]' - * Warning: by convention @string are case sensitive - */ - function getIconOrTxt($ext,$def=NULL) { - // e.g. @STRING{icon_pdf="http://mywebsite/pdf.png"} - if ($def==NULL) { $def=$ext; } - $stringkey = strtolower('icon_'.$ext); - if (isset($_GET[Q_DB]->stringdb[$stringkey])){ - $str='['.$def.']'; - } else { - $str='['.$def.']'; - } - return $str; - } - - /** MG: Read the url specified as the bibtex entry key $bibentry and return the link with icon or text + /** Read the bibtex field $bibfield and return a link with icon or text * e.g. given the bibtex entry: @article{myarticle, pdf={myarticle.pdf}}, * $bibtexentry->getLink('pdf') creates a link to myarticle.pdf using the text '[pdf]' or the pdf icon specified in the bibtex file (cf. getIconOrTxt) - * getLink($bibentry,$icon,$def) specifies the icon key $icon and default text $def. + * getLink($bibfield,$icon,$def) specifies the icon key $icon and default text $def. */ - function getLink($bibentry,$icon=NULL,$def=NULL) { - if ($icon==NULL) { $icon=$bibentry; } + function getLink($bibfield,$icon=NULL,$def=NULL) { + if ($icon==NULL) { $icon=$bibfield; } $str = $this->getIconOrTxt($icon,$def); - if ($this->hasField($bibentry)) { - return ' '.$str.''; + if ($this->hasField($bibfield)) { + return ' '.$str.''; } return ''; } - /** MG: DOI are a special kind of links, where the url depends on the doi */ + /* a few specializations of getLink */ + + /** returns a "[url]" link if relevant. modified to exploit the new method, while keeping backward compatibility */ + function getUrlLink() { + return $this->getLink('url'); + } + + /** returns a "[bib]" link if relevant */ + function getBibLink() { + $bibstr = $this->getIconOrTxt('bib'); + $href = 'href="'.$this->getURL().'"'; + $link = "getKey()."\" {$href}>$bibstr"; + return $link; + } + + + /** DOI are a special kind of links, where the url depends on the doi */ function getDoiLink() { $str = $this->getIconOrTxt('doi'); if ($this->hasField('doi')) { @@ -1101,7 +1043,7 @@ class BibEntry { return ''; } - /** MG: GS are a special kind of links, where the url depends on the google scholar id */ + /** GS are a special kind of links, where the url depends on the google scholar id */ function getGSLink() { $str = $this->getIconOrTxt('gsc','cites'); // Google Scholar ID @@ -1111,17 +1053,40 @@ class BibEntry { return ''; } - /** returns a "[url]" link if relevant */ /* MG: modified to exploit the new method, while keeping backward compatibility */ - function getUrlLink() { - return $this->getLink('url'); + /** replace [$ext] with an icon whose url is defined in a string + * e.g. getIconOrTxt('pdf') will show the icon defined by @string{icon_pdf=""} or print '[pdf]' + * or getIconOrTxt('pdf','paper') will show the icon defined by @string{icon_pdf=""} or print '[paper]' + * The replacement text is also used if the url does not point to a valid file (using the "alt" property of the "img" html tag) + * Warning: by convention @string are case sensitive + */ + function getIconOrTxt($ext,$def=NULL) { + // e.g. @STRING{icon_pdf="http://mywebsite/pdf.png"} + if ($def==NULL) { $def=$ext; } + $stringkey = strtolower('icon_'.$ext); + if (isset($_GET[Q_DB]->stringdb[$stringkey])){ + $str='['.$def.']'; + } else { + $str='['.$def.']'; + } + return $str; } + + /** Reruns the abstract */ function getAbstract() { if ($this->hasField('abstract')) return $this->getField('abstract'); else return ''; } + /** + * Returns the last name of an author name. + */ + function getLastName($author){ + list($firstname, $lastname) = splitFullName($author); + return $lastname; + } + /** Has this entry the given field? */ function hasField($name) { @@ -1144,7 +1109,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? */ @@ -1214,7 +1179,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) { @@ -1228,18 +1193,35 @@ class BibEntry { */ function formattedAuthors() { return $this->getFormattedAuthorsImproved(); } - /** Adds to getFormattedAuthors() the home page links and returns a string (not an array) + /** Adds to getFormattedAuthors() the home page links and returns a string (not an array). Is configured with BIBTEXBROWSER_AUTHOR_LINKS and COMMA_NAMES. */ function getFormattedAuthorsImproved() { $array_authors = $this->getFormattedAuthors(); - foreach ($array_authors as $k => $author) { - $array_authors[$k]=$this->addHomepageLink($author); + + if (BIBTEXBROWSER_AUTHOR_LINKS=='homepage') { + foreach ($array_authors as $k => $author) { + $array_authors[$k]=$this->addHomepageLink($author); + } + } + + if (BIBTEXBROWSER_AUTHOR_LINKS=='resultpage') { + foreach ($array_authors as $k => $author) { + $array_authors[$k]=$this->addAuthorPageLink($author); + } } if (COMMA_NAMES) {$sep = '; ';} else {$sep = ', ';} + return implode($sep ,$array_authors); } + /** adds a link to the author page */ + function addAuthorPageLink($author) { + $link = makeHref(array(Q_AUTHOR => $author)); + return "$author"; + } + + /** Returns the authors of this entry as an array in a canonical form */ function getCanonicalAuthors() { $authors = array(); @@ -1263,7 +1245,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; } @@ -1304,8 +1286,7 @@ class BibEntry { if (COMMA_NAMES) {$sep = '; ';} else {$sep = ', ';} return implode($sep, $editors).', '.(count($editors)>1?'eds.':'ed.'); } - - + /** Returns the year of this entry? */ function getYear() { return $this->getField('year'); @@ -1328,29 +1309,29 @@ class BibEntry { function getFields() { return $this->fields; } - - /** Returns the identification number. */ - function getId() { - return $this->id; - } - + /** Returns the abbreviation. */ function getAbbrv() { - if (ABBRV_TYPE == 'default') return $this->id; - if (ABBRV_TYPE == 'year') return $this->getYear(); + if (ABBRV_TYPE == 'index') return $this->index; + if (ABBRV_TYPE == 'none') return ''; + if (ABBRV_TYPE == 'key') return '['.$this->getKey().']'; + if (ABBRV_TYPE == 'year') return '['.$this->getYear().']'; if (ABBRV_TYPE == 'x-abbrv') { if ($this->hasField('x-abbrv')) {return $this->getField('x-abbrv');} - // otherwise - return $this->getKey(); - } + return $this->abbrv; + } - die('Unknown configuration value for ABBRV_TYPE'); + // otherwise it is a user-defined function in bibtexbrowser.local.php + $f = ABBRV_TYPE; + return $f($this); } /** Sets the abbreviation (e.g. [OOPSLA] or [1]) */ function setAbbrv($abbrv) { - return $this->id = $abbrv; + //if (!is_string($abbrv)) { throw new Exception('Illegal argument'); } + $this->abbrv = $abbrv; + return $this; } function getText() { @@ -1358,7 +1339,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) { @@ -1383,13 +1364,13 @@ class BibEntry { } - /** returns a "[bib]" link if relevant */ - /** MG: added the Bib icon */ - function getBibLink() { - $bibstr = $this->getIconOrTxt('bib'); - $href = 'href="'.$this->getURL().'"'; - $link = "getKey()."\" {$href}>$bibstr"; - return $link; + /** Outputs HTML line according to layout */ + function toHTML() { + switch(LAYOUT) { + case 'list': $this->toLI(); break; + case 'table': $this->toTR(); break; + case 'deflist': $this->toDD(); break; + } } @@ -1397,24 +1378,27 @@ class BibEntry { */ function toTR() { echo '
      '; - echo ' '; + echo ' '; echo '\n"; } - /** MG: Outputs an LI line (
    1. ) with spans for each element, using the value attribute the abbrev. (does not work with x-abbrv) */ + /** Outputs an LI line (
    2. ) with spans for each element, using the value attribute the abbrev. (does not work with x-abbrv) */ function toLI() { echo '
    3. '; - echo ''; + echo ''; echo bib2html($this); echo "
    4. \n"; } - /** MG: Outputs an DL line (
      +
      ) */ + /** Outputs an DL line (
      +
      ) */ function toDD() { - echo '
      '.$this->getAbbrv().'
      '; + echo '
      '.$this->getAbbrv().'
      '; echo bib2html($this); echo "
      \n"; } @@ -1468,8 +1452,8 @@ class BibEntry { } // referrer, the id pf a collection of objects - // see also http://www.openurl.info/registry/docs/pdf/info-sid.pdf - $url_parts[]='rfr_id='.s3988('info:sid/'.$_SERVER['HTTP_HOST'].':'.$_GET[Q_FILE]); + // see also http://www.openurl.info/registry/docs/pdf/info-sid.pdf + $url_parts[]='rfr_id='.s3988('info:sid/'.$_SERVER['HTTP_HOST'].':'.@$_GET[Q_FILE]); $url_parts[]='rft.date='.s3988($this->getYear()); @@ -1526,24 +1510,75 @@ class BibEntry { } +function layoutHeaderHTML() { + switch(LAYOUT) { /* switch for different layouts */ + case 'list': + echo '
        '; + break; + case 'table': + echo '
      ['.$this->getAbbrv().']'; + //echo ''; + + echo $this->getAbbrv().''; echo bib2html($this); echo "
      '; + break; + case 'deflist': + echo '
      '; + break; + } +} + +function layoutFooterHTML() { + switch(LAYOUT) { + case 'list': + echo ''; + break; + case 'table': + echo '
      '; + break; + case 'deflist': + echo ''; + break; + } +} + /** this function encapsulates the user-defined name for bib to HTML*/ function bib2html(&$bibentry) { $function = BIBLIOGRAPHYSTYLE; return $function($bibentry); } -/**bibtexbrowser uses this function which encapsulates the user-defined sections*/ +/** encapsulates the user-defined sections. @nodoc */ function _DefaultBibliographySections() { $function = BIBLIOGRAPHYSECTIONS; return $function(); } +/** compares two instances of BibEntry by modification time + */ +function compare_bib_entry_by_mtime($a, $b) +{ + return -($a->getTimestamp()-$b->getTimestamp()); +} + +/** compares two instances of BibEntry by year + */ +function compare_bib_entry_by_year_and_month($a, $b) +{ + $year_cmp = -strcmp($a->getYear(),$b->getYear()); + if ($year_cmp==0) { return compare_bib_entry_by_month($a, $b);} + return $year_cmp; +} + +/** compares two instances of BibEntry by title + */ +function compare_bib_entry_by_title($a, $b) +{ + return strcmp($a->getTitle(),$b->getTitle()); +} + -/** Compares two instances of BibEntry by month +/** compares two instances of BibEntry by month * @author Jan Geldmacher */ function compare_bib_entry_by_month($a, $b) -{ +{ // this was the old behavior // return strcmp($a->getKey(),$b->getKey()); @@ -1574,15 +1609,15 @@ function compare_bib_entry_by_month($a, $b) $val_a = array_search(strtolower($a->fields[$sort_key]), $sort_order_values); $val_b = array_search(strtolower($b->fields[$sort_key]), $sort_order_values); - if (($val_a == FALSE && $val_b == FALSE) || ($val_a == $val_b)) { + if (($val_a === FALSE && $val_b === FALSE) || ($val_a === $val_b)) { //neither a nor b are in the search array or a=b -> both are equal $retval=0; } - elseif (($val_a == FALSE) || ($val_a < $val_b)) { + elseif (($val_a === FALSE) || ($val_a < $val_b)) { //a is not in the search array or a b is greater $retval=-1; } - elseif (($val_b == FALSE) || (($val_a > $val_b))){ + elseif (($val_b === FALSE) || (($val_a > $val_b))){ //b is not in the search array or a>b -> a is greater $retval=1; } @@ -1591,19 +1626,24 @@ function compare_bib_entry_by_month($a, $b) return $order*$retval; } -/** the default sections */ +/** is the default sectioning for AcademicDisplay (books, articles, proceedings, etc. ) */ function DefaultBibliographySections() { 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( @@ -1624,20 +1664,13 @@ return } -?>getTitle(); @@ -1732,7 +1765,104 @@ function DefaultBibliographyStyle(&$bibentry) { } -?> +define('BIBLIOGRAPHYSTYLE','JanosBibliographyStyle'); + +*/ +function JanosBibliographyStyle(&$bibentry) { + $title = $bibentry->getTitle(); + $type = $bibentry->getType(); + + $entry=array(); + + // author + if ($bibentry->hasField('author')) { + $entry[] = $bibentry->formattedAuthors(); + } + + // title + $title = '"'.$title.'"'; + if ($bibentry->hasField('url')) $title = ' '.$title.''; + $entry[] = $title; + + + // now the origin of the publication is in italic + $booktitle = ''; + + if (($type=="misc") && $bibentry->hasField("note")) { + $booktitle = $bibentry->getField("note"); + } + + if ($type=="inproceedings") { + $booktitle = 'In '.$bibentry->getField(BOOKTITLE); + } + + if ($type=="incollection") { + $booktitle = 'Chapter in '.$bibentry->getField(BOOKTITLE); + } + + if ($type=="article") { + $booktitle = 'In '.$bibentry->getField("journal"); + } + + + + //// ******* EDITOR + $editor=''; + if ($bibentry->hasField(EDITOR)) { + $editor = $bibentry->getFormattedEditors(); + } + + if ($booktitle!='') { + if ($editor!='') $booktitle .=' ('.$editor.')'; + $entry[] = ''.$booktitle.''; + } + + + $publisher=''; + if ($type=="phdthesis") { + $publisher = 'PhD thesis, '.$bibentry->getField(SCHOOL); + } + + if ($type=="mastersthesis") { + $publisher = 'Master\'s thesis, '.$bibentry->getField(SCHOOL); + } + if ($type=="techreport") { + $publisher = 'Technical report, '.$bibentry->getField("institution"); + } + if ($bibentry->hasField("publisher")) { + $publisher = $bibentry->getField("publisher"); + } + + if ($publisher!='') $entry[] = $publisher; + + if ($bibentry->hasField('volume')) $entry[] = "vol. ".$bibentry->getField("volume"); + if ($bibentry->hasField('number')) $entry[] = 'no. '.$bibentry->getField("number"); + + if ($bibentry->hasField('address')) $entry[] = $bibentry->getField("address"); + + if ($bibentry->hasField('pages')) $entry[] = str_replace("--", "-", "pp. ".$bibentry->getField("pages")); + + + if ($bibentry->hasField(YEAR)) $entry[] = $bibentry->getYear(); + + $result = implode(", ",$entry).'.'; + + // some comments (e.g. acceptance rate)? + if ($bibentry->hasField('comment')) { + $result .= " (".$bibentry->getField("comment").")"; + } + + // add the Coin URL + $result .= "\n".$bibentry->toCoins(); + + return $result; +} + @@ -1743,40 +1873,34 @@ function DefaultBibliographyStyle(&$bibentry) { // ---------------------------------------------------------------------- -/** - * Given an array of parameter, creates a query string +/** creates a query string given an array of parameter, with all specifities of bibtexbrowser_ (such as adding the bibtex file name &bib=foo.bib */ function createQueryString($array_param) { - // first we add the name of the bib file - $array_param[Q_FILE] = urlencode($_GET[Q_FILE]); - + if (isset($_GET[Q_FILE]) && !isset($array_param[Q_FILE])) { + // first we add the name of the bib file + $array_param[Q_FILE] = urlencode($_GET[Q_FILE]); + } // 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); } -/** - * Given a query, an array of key value pairs, returns a href string - * of the form: href="?bib=testing.bib&search=JML. +/** returns a href string of the form: href="?bib=testing.bib&search=JML. +Based on createQueryString. +@nodoc */ function makeHref($query = NULL) { return 'href="?'. createQueryString($query) .'"'; } -/** - * Returns the last name of an author name. - */ -function getLastName($author){ - list($firstname, $lastname) = splitFullName($author); - return $lastname; -} -/** - * Returns the splitted name of an author name as an array. The argument is assumed to be - * or . +/** returns the splitted name of an author name as an array. The argument is assumed to be + "FirstName LastName" or "LastName, FirstName". */ function splitFullName($author){ $author = trim($author); @@ -1798,17 +1922,16 @@ function splitFullName($author){ } -/** New undocumented feature, used by Benoit Baudry - * see http://www.irisa.fr/triskell/perso_pro/bbaudry/publications.php - * - * $_GET['library']=1; - * $_GET['bib']='metrics.bib'; - * $_GET['all']=1; - * include( 'bibtexbrowser.php' ); - * setDB(); - * new IndependentYearMenu(); - * new Dispatcher(); - * +/** outputs an horizontal year-based menu +usage: +
      +  $_GET['library']=1;
      +  $_GET['bib']='metrics.bib';
      +  $_GET['all']=1;
      +  include( 'bibtexbrowser.php' );
      +  setDB();
      +  new IndependentYearMenu();
      +
      */ class IndependentYearMenu { function IndependentYearMenu() { @@ -1827,45 +1950,29 @@ class IndependentYearMenu { } } -/** Class to encapsulates the header formatting and the powered by footer */ -class BibtexBrowserDisplay { - /** the title */ - var $title; - - function getTitle() { return $this->title; } - - function display() { /* unimplemented */ } - - /** returns the url of this display (e.g. base on the query)*/ - function getURL() { return '';} - - /** returns the url of the RSS */ - function getRSS() { return '';} - - /** Returns the powered by part */ - function poweredby() { - $poweredby = "\n".'
      '; - $poweredby .= ''; - $poweredby .= 'Powered by bibtexbrowser'; - $poweredby .= '
      '."\n"; - return $poweredby; - } +/** Returns the powered by part. @nodoc */ +function poweredby() { + $poweredby = "\n".'
      '; + $poweredby .= ''; + $poweredby .= 'Powered by bibtexbrowser'; + $poweredby .= '
      '."\n"; + return $poweredby; + } - function formatedHeader() { return "
      {$this->title}
      \n";} - /** Adds a touch of AJAX in bibtexbrowser to display bibtex entries inline. - * It uses the HIJAX design pattern: the Javascript code fetches the normal bibtex HTML page - * and extracts the bibtex. - * In other terms, URLs and content are left perfectly optimized for crawlers - * Note how beautiful is this piece of code thanks to JQuery. - */ - function javascript() { +/** ^^adds a touch of AJAX in bibtexbrowser to display bibtex entries inline. + It uses the HIJAX design pattern: the Javascript code fetches the normal bibtex HTML page + and extracts the bibtex. + In other terms, URLs and content are left perfectly optimized for crawlers + Note how beautiful is this piece of code thanks to JQuery.^^ + */ +function javascript() { // we use jquery with the official content delivery URLs // Microsoft and Google also provide jquery with their content delivery networks ?> + $db = zetDB('metrics.bib'); + $menu = new MenuManager(); + $menu->setDB($db); + $menu->year_size=100;// should display all years :) + $menu->display(); + */ -class MenuManager extends BibtexBrowserDisplay { +class MenuManager { /** The bibliographic database, an instance of class BibDataBase. */ var $db; - /** Creates a new display manager that uses the given bib database. */ - function MenuManager(&$db) { + var $type_size = TYPES_SIZE; + var $year_size = YEAR_SIZE; + var $author_size = AUTHORS_SIZE; + var $tag_size = TAGS_SIZE; + + function MenuManager() { + } + + /** sets the database that is used to create the menu */ + function setDB(&$db) { $this->db =$db; + return $this; } + function getTitle() { + return ''; + } + + /** function called back by HTMLWrapper */ function display() { echo $this->searchView().'
      '; @@ -1942,18 +2070,18 @@ class MenuManager extends BibtexBrowserDisplay { /** Displays and controls the types menu in a table. */ function typeVC() { - $types = array(); - $types[''] = 'all types'; - foreach ($this->db->getTypes() as $type) { - $types[$type] = $type; - } + $types = array(); + foreach ($this->db->getTypes() as $type) { + $types[$type] = $type; + } + $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, TYPES_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. */ @@ -1968,7 +2096,7 @@ class MenuManager extends BibtexBrowserDisplay { else $page = 1; - $this->displayMenu('Authors', $authors, $page, AUTHORS_SIZE, Q_AUTHOR_PAGE, + $this->displayMenu('Authors', $authors, $page, $this->author_size, Q_AUTHOR_PAGE, Q_AUTHOR); } @@ -1983,7 +2111,7 @@ class MenuManager extends BibtexBrowserDisplay { } else $page = 1; - if (count($tags)>0) $this->displayMenu('Keywords', $tags, $page, TAGS_SIZE, Q_TAG_PAGE, + if (count($tags)>0) $this->displayMenu('Keywords', $tags, $page, $this->tag_size, Q_TAG_PAGE, Q_TAG); } @@ -1996,10 +2124,10 @@ class MenuManager extends BibtexBrowserDisplay { if (isset($_GET[Q_YEAR_PAGE])) { $page = $_GET[Q_YEAR_PAGE]; } - else $page = 1; +else $page = 1; - $this->displayMenu('Years', $years, $page, YEAR_SIZE, Q_YEAR_PAGE, + $this->displayMenu('Years', $years, $page, $this->year_size, Q_YEAR_PAGE, Q_YEAR); } @@ -2029,9 +2157,9 @@ class MenuManager extends BibtexBrowserDisplay { - - - + + @@ -2039,7 +2167,7 @@ class MenuManager extends BibtexBrowserDisplay { - @@ -2060,31 +2188,19 @@ class MenuManager extends BibtexBrowserDisplay { $start, $end) { $result = ''; - /* // commented after the usability remarks of Benoit Combemale - // fast (2 pages) reverse (<<) - if ($start - $pageSize > 0) { - $href = makeHref(array($queryKey => $page - 2,'menu'=>'')); - $result .= '«\n"; - }*/ // (1 page) reverse (<) if ($start > 0) { - $href = makeHref(array($queryKey => $page - 1,'menu'=>'')); + $href = makeHref(array($queryKey => $page - 1,'menu'=>''));//menuPageBar $result .= '[prev]\n"; } // (1 page) forward (>) if ($end < $numEntries) { - $href = makeHref(array($queryKey => $page + 1,'menu'=>'')); + $href = makeHref(array($queryKey => $page + 1,'menu'=>''));//menuPageBar $result .= '[next]\n"; } - /*// commented after the usability remarks of Benoit Combemale - // fast (2 pages) forward (>>) - if (($end + $pageSize) < $numEntries) { - $href = makeHref(array($queryKey => $page + 2,'menu'=>'')); - $result .= '»\n"; - }*/ return $result; } @@ -2093,7 +2209,7 @@ class MenuManager extends BibtexBrowserDisplay { * the end index (exclusive). For each menu, the following form of * string is printed: * - * + * * Cheon, Yoonsik *
      */ @@ -2110,170 +2226,202 @@ class MenuManager extends BibtexBrowserDisplay { } } +if (!function_exists('query2title')) { /** transforms an array representing a query into a formatted string */ function query2title(&$query) { - if (isset($query[Q_BIBLIOGRAPHY])) return 'Publications in ' . $_SERVER['PHP_SELF']; + // special case + if (isset($query[Q_BIBLIOGRAPHY])) return 'Publications in ' . htmlspecialchars($_SERVER['PHP_SELF']); + $headers = array(); foreach($query as $k=>$v) { - if($k == '_author') { $k = 'author'; } - if($k == 'type') { $v = substr($v,1,strlen($v)-2); } - $headers[$k] = ucwords($k).': '.ucwords($v); + 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(htmlspecialchars($v)); } // special cases - if (isset($headers[Q_ALL])) $headers[Q_ALL] = 'Publications in '.$_GET[Q_FILE]; - if (isset($headers[Q_AUTHOR])) $headers[Q_AUTHOR] = 'Publications of '.$_GET[Q_AUTHOR]; + if (isset($headers[Q_ALL])) $headers[Q_ALL] = 'Publications in '.htmlspecialchars($_GET[Q_FILE]); + if (isset($headers[Q_AUTHOR])) $headers[Q_AUTHOR] = 'Publications of '.htmlspecialchars($_GET[Q_AUTHOR]); return join(' & ',$headers); } +} - -/** Class to display a result as a set of pages. */ -class PagedDisplay extends BibtexBrowserDisplay { - /** the bib entries to display. */ - var $result; - - /** the page number to display. */ - var $page; - - /** the total number of pages to display. */ - var $noPages; - - /** the start index to display. */ - var $startIndex; - - /** the end index to display. */ - var $endIndex; - - /** the content strategy (cf. pattern strategy) */ - var $contentStrategy; - - /** the query to reinject in links to different pages */ - var $filter; - - /** Creates an instance with the given entries and header. */ - function PagedDisplay(&$result, $filter) { - $this->result = $result; - $this->filter = $filter; - // requesting a different page of the result view? - if (isset($_GET[Q_RESULT])) { - $this->setPage($_GET[Q_RESULT]); - } else $this->page = 1; - $this->setTitle(); - $this->contentStrategy = new DefaultContentStrategy(); +/** displays the latest modified bibtex entries. +usage: +
      +  $db = zetDB('metrics.bib');
      +  $d = new NewEntriesDisplay();
      +  $d->setDB($db);
      +  $d->setN(7);// optional 
      +  $d->display();
      +
      + */ +class NewEntriesDisplay { + var $n=5; + var $db; + + function setDB(&$bibdatabase) { + $this->db = $bibdatabase; } + + function setN($n) {$this->n = $n;return $this;} - /** sets the $this->title of BibtexBrowserDisplay based on the $filter */ - function setTitle() { - $this->title = query2title($this->filter); - if ($this->page>1) $this->title.=' - page '.$this->page; + /** sets the entries to be shown */ + function setEntries(&$entries) { + $this->db = createBibDataBase(); + $this->db->bibdb = $entries; } - /** Sets the page number to display. */ - function setPage($page) { - $this->page = $page; + /** Displays a set of bibtex entries in an HTML table */ + function display() { + $array = $this->db->getLatestEntries($this->n); + $delegate = createBasicDisplay(); + $delegate->setEntries($array); + $delegate->display(); } +} - /** overrides */ - function formatedHeader() { return '
      '.$this->title.' '.createRSSLink($this->filter).'
      ';} - - /** overrides */ - function getURL() { return '?'.createQueryString($this->filter);} - /** overrides */ - function getRSS() { return BIBTEXBROWSER_URL.'?'.createQueryString($this->filter).'&rss';} +/** displays the entries by year in reverse chronological order. +usage: +
      +  $db = zetDB('metrics.bib');
      +  $d = new YearDisplay();
      +  $d->setDB($db);
      +  $d->display();
      +
      +*/ +class YearDisplay { + + /** is an array of strings representing years */ + var $yearIndex; - /** Displays the entries preceded with the header. */ - function display() { + function setDB(&$bibdatabase) { + $this->setEntries($bibdatabase->bibdb); + } - $page = $this->page; + /** creates a YearDisplay */ + function setOptions(&$options) {} - // print error message if no entry. - if (empty($this->result)) { - echo "No match found!\n"; - return; + function getTitle() {return '';} + + /** sets the entries to be shown */ + function setEntries(&$entries) { + $this->entries = $entries; + $db= createBibDataBase(); + $db->bibdb = $entries; + $this->yearIndex = $db->yearIndex(); + } + + /** Displays a set of bibtex entries in an HTML table */ + function display() { + $delegate = createBasicDisplay(); + $delegate->setEntries($this->entries); + $index = count($this->entries); + foreach($this->yearIndex as $year) { + $x = array(); + uasort($x,'compare_bib_entry_by_month'); + foreach($this->entries as $e) { + if ($e->getYear() == $year) { + $x[] = $e; + } + } + + if (count($x)>0) { + echo '
      '.$year.'
      '; + $delegate->setEntries($x); + $delegate->display(); + } + + $index = $index - count($x); } + } +} - $this->noPages = ceil(count($this->result) / PAGE_SIZE); - - if ($this->noPages>1) $this->displayPageBar($this->noPages, $page); - - $this->startIndex = ($page - 1) * PAGE_SIZE; - $this->endIndex =$this->startIndex + PAGE_SIZE; - // $this->setLayout(); - - $this->contentStrategy->display($this); - if ($this->noPages>1) $this->displayPageBar($this->noPages, $page); - - echo $this->poweredby(); - - if (BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT) { - $this->javascript(); - } +/** displays the summary information of all bib entries. +usage: +
      +  $db = zetDB('metrics.bib');
      +  $d = new SimpleDisplay();
      +  $d->setDB($db);
      +  $d->display();
      +
      + */ +class SimpleDisplay { + + var $options = array(); + + function setDB(&$bibdatabase) { + $this->setEntries($bibdatabase->bibdb); } - function isDisplayed($index) { - if ($index >= $this->startIndex && $index < $this->endIndex) return true; - return false; + /** sets the entries to be shown */ + function setEntries(&$entries) { + $this->entries = $entries; } + function indexUp() { + $index=1; + foreach ($this->entries as $bib) { + $bib->setAbbrv((string)$index++); + } // end foreach + return $this->entries; + } + + function newest(&$entries) { + return array_slice($entries,0,BIBTEXBROWSER_NEWEST); + } - /** Displays a page bar consisting of clickable page numbers. */ - function displayPageBar($noPages, $page) { - - // bug found by benoit, first we have to reset the q_result - $this->filter[Q_RESULT] = 1; - - $barSize = 10; // *2 - $start = ($page - $barSize) > 0 ? $page - $barSize : 1; - $end = min($noPages, $start + $barSize * 2); - - echo ''; - } -} /** creates an RSS link with text or image depending on the environment */ function createRSSLink($filter) { @@ -2304,23 +2452,7 @@ class DefaultContentStrategy { } krsort($years); - switch(LAYOUT) { /* MG: added switch for different layouts */ - case 'list': - ?> -
        - -
      +
      menuPageBar($pageKey, $numEntries, $page, $pageSize, $startIndex, $endIndex);?>
      + displayMenuItems($list, $startIndex, $endIndex, $targetKey); ?>
      - -
      - result)-(($display->page-1)*PAGE_SIZE); @@ -2348,137 +2480,96 @@ class DefaultContentStrategy { foreach ($entries as $bib) { if ($display->isDisplayed($index)) { $bib->setAbbrv($refnum--); - switch(LAYOUT) { - case 'list': $bib->toLI(); break; - case 'table': $bib->toTR(); break; - case 'deflist': $bib->toDD(); break; - } + $bib->toHTML(); } $index++; } // end foreach } - switch(LAYOUT) { - case 'list': - ?> - - -
      - - - + Sorry, this bib entry does not exist. + Back to bibtexbrowser + - Sorry, this bib entry does not exist. - Back to bibtexbrowser - title = $title; return $this; } + function getTitle() { return @$this->title ; } + function display() { + echo 'no result found, sorry.'; } } +/** displays the publication records sorted by publication types (as configured by constant BIBLIOGRAPHYSECTIONS). +usage: +
      +  $db = zetDB('metrics.bib');
      +  $d = new AcademicDisplay();
      +  $d->setDB($db);
      +  $d->display();
      +
      + */ +class AcademicDisplay { -/** Class to display the publication records sorted by publication types. */ -class AcademicDisplay extends BibtexBrowserDisplay { - - /** the query */ - var $query; + function getTitle() { return $this->title; } + function setTitle($title) { $this->title = $title; return $this; } - /** - * $entries: an array of bib entries - * $query: the array representing the query - */ - function AcademicDisplay(&$entries,&$query) { - $this->query=$query; - $this->db=new BibDataBase(); - $this->db->bibdb = $entries; - $this->title = query2title($query); + function setDB(&$bibdatabase) { + $this->setEntries($bibdatabase->bibdb); + } + + /** sets the entries to be shown */ + function setEntries(&$entries) { + $this->entries = $entries; } - - /** overrides */ - function formatedHeader() { return '
      '.$this->title.' '.createRSSLink($this->query).'
      ';} - /** 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"; - switch (LAYOUT) { - case 'list': - echo '
        '."\n"; - break; - case 'table': - echo ''."\n"; - break; - case 'deflist': - echo '
        '."\n"; - break; - } + layoutHeaderHTML(); - // by default the abbreviation is incermented over all + // by default the abbreviation is incremented over all // searches + + // since we don't know before hand all section, we can not index in decreasing order static $count; if ($count == NULL) { $count = 1; } // init $id = $count; foreach ($entries as $bib) { - $bib->setAbbrv($id++); - switch(LAYOUT) { - case 'list': $bib->toLI(); break; - case 'table': $bib->toTR(); break; - case 'deflist': $bib->toDD(); break; - } + $bib->setIndex($id++); + $bib->toHTML(); } // end foreach $count = @$count + count($entries); - switch(LAYOUT) { - case 'list': - ?> - - -
        - - - db = createBibDataBase(); + $this->db->bibdb = $this->entries; + + foreach (_DefaultBibliographySections() as $section) { $this->search2html($section['query'],$section['title']); } - - echo $this->poweredby(); - - if (BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT) { - $this->javascript(); - } - } } @@ -2486,24 +2577,36 @@ class AcademicDisplay extends BibtexBrowserDisplay { -/** Class to display a single bib entry. - * This view is optimized for Google Scholar - * */ -class BibEntryDisplay extends BibtexBrowserDisplay { +/** displays a single bib entry. +usage: +
        +  $db = zetDB('metrics.bib');
        +  $dis = new BibEntryDisplay($db->getEntryByKey('Schmietendorf2000'));
        +  $dis->display();
        +
        +notes: +- the top-level header (usually <H1>) must be done by the caller. +- this view is optimized for Google Scholar + */ +class BibEntryDisplay { /** the bib entry to display */ var $bib; - /** Creates an instance with the given bib entry and header. - * It the object is an instance of BibIndexEntry, it may be - * mutated to read the rest of the fields. - */ - function BibEntryDisplay(&$bibentry) { - $this->bib = $bibentry; - $this->title = $this->bib->getTitle().' (bibtex)'; + function BibEntryDisplay($bib=null) { + $this->bib = $bib; + } + + function setEntries(&$entries) { + $this->bib = $entries[0]; //$this->title = $this->bib->getTitle().' (bibtex)'.$this->bib->getUrlLink(); } + /** returns the title */ + function getTitle() { + return $this->bib->getTitle().' (bibtex)'; + } + /** 2011/10/02: new display, inspired from Tom Zimmermann's home page */ function displayOnSteroids() { $subtitle = '
        by '.$this->bib->getFormattedAuthorsImproved().'
        '; @@ -2528,7 +2631,6 @@ class BibEntryDisplay extends BibtexBrowserDisplay { echo '
        '; //echo $this->display_old(); echo $this->displayOnSteroids(); - echo $this->poweredby(); echo '
        '; } @@ -2636,7 +2738,7 @@ class BibEntryDisplay extends BibtexBrowserDisplay { foreach($this->bib->getArrayOfCommaSeparatedAuthors() as $author) { $result[] = array('DC.Creator',$author); } - $result[] = array('DC.Date',$this->bib->getYear()); + $result[] = array('DC.Issued',$this->bib->getYear()); } // --------------------------------- BEGIN METADATA EPRINTS @@ -2713,10 +2815,15 @@ class BibEntryDisplay extends BibtexBrowserDisplay { // DATABASE MANAGEMENT // ---------------------------------------------------------------------- -/** - * Abstraction of bibliographic database to contain a set of - * bibliographic entries and maintain them. - */ +/** represents a bibliographic database that contains a set of bibliographic entries. +usage: +
        +$db = new BibDataBase();
        +$db->load('metrics.bib');
        +$query = array('author'=>'martin', 'year'=>2008);
        +foreach ($db->multisearch($query) as $bibentry) { echo $bibentry->getTitle(); }
        +
        +*/ class BibDataBase { /** A hash table from keys (e.g. Goody1994) to bib entries (BibEntry instances). */ var $bibdb; @@ -2725,13 +2832,47 @@ class BibDataBase { var $stringdb; /** Creates a new database by parsing bib entries from the given - * file. */ + * file. (backward compatibility) */ function load($filename) { - $db = new BibDBBuilder($filename, $this->bibdb, $this->stringdb); - //print_r($parser); - $this->bibdb = $db->builtdb; - $this->stringdb = $db->stringdb; - //print_r($this->stringdb); + $this->update($filename); + } + + /** Updates a database (replaces the new bibtex entries by the most recent ones) */ + function update($filename) { + + $empty_array = array(); + $db = createBibDBBuilder(); + $db->setData($empty_array, $this->stringdb); + $db->build($filename); + + $this->stringdb = array_merge($this->stringdb, $db->stringdb); + + $result = $db->builtdb; + + + foreach ($result as $b) { + // new entries: + if (!isset($this->bibdb[$b->getKey()])) { + //echo 'adding...
        '; + $this->bibdb[$b->getKey()] = $b; + } + // update entry + else if (isset($this->bibdb[$b->getKey()]) && ($b->getText() !== $this->bibdb[$b->getKey()]->getText())) { + //echo 'replacing...
        '; + $this->bibdb[$b->getKey()] = $b; + } + } + + // some entries have been removed + foreach ($this->bibdb as $e) { + if (!isset($result[$e->getKey()]) + && $e->filename==$filename // bug reported by Thomas on Dec 4 2012 + ) { + //echo 'deleting...
        '; + unset($this->bibdb[$e->getKey()]); + } + } + } /** Creates a new empty database */ @@ -2740,6 +2881,15 @@ class BibDataBase { $this->stringdb = array(); } + /** Returns the $n latest modified bibtex entries/ */ + function getLatestEntries($n) { + $order='compare_bib_entry_by_mtime'; + $array = $this->bibdb; // array passed by value + uasort($array, $order); + $result = array_slice($array,0,$n); + return $result; + } + /** Returns all entries as an array. Each entry is an instance of * class BibEntry. */ function getEntries() { @@ -2779,7 +2929,7 @@ class BibDataBase { foreach ($this->bibdb as $bib) { foreach($bib->getRawAuthors() as $a){ //we use an array because several authors can have the same lastname - @$result[getLastName($a)][$bib->formatAuthor($a)]++; + @$result[$bib->getLastName($a)][$bib->formatAuthor($a)]++; } } ksort($result); @@ -2801,7 +2951,7 @@ class BibDataBase { $result = array(); foreach ($this->bibdb as $bib) { if (!$bib->hasField("keywords")) continue; - $tags =preg_split('/[,;]/', $bib->getField("keywords")); + $tags =preg_split('/[,;\\/]/', $bib->getField("keywords")); foreach($tags as $a){ $ta = trim($a); $result[$ta] = $ta; @@ -2844,7 +2994,6 @@ class BibDataBase { /** Returns an array of bib entries (BibEntry) that satisfy the query * $query is an hash with entry type as key and searched fragment as value - * the returned array is sorted by year */ function multisearch($query) { if (count($query)<1) {return array();} @@ -2867,50 +3016,67 @@ class BibDataBase { foreach ($this->bibdb as $bib) { $entryisselected = true; - $akey = $bib->getYear().$bib->getKey(); foreach ($query as $field => $fragment) { + $field = strtolower($field); if ($field==Q_SEARCH) { // we search in the whole bib entry if (!$bib->hasPhrase($fragment)) { $entryisselected = false; + break; } } else if ($field==Q_EXCLUDE) { if ($bib->hasPhrase($fragment)) { $entryisselected = false; + break; + } + } + 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; + break; } } else if ($field==Q_BIBLIOGRAPHY) { if ( !array_key_exists( $bib->getKey(), $citations ) ) { $entryisselected = false; - } else { - $akey = $citations[$bib->getKey()]; + break; } } else if ($field==Q_KEYS) { if ( ! in_array( $bib->getKey(), $citations ) ) { $entryisselected = false; + break; } - } else { + } + else { if (!$bib->hasPhrase($fragment, $field)) { $entryisselected = false; + break; } } - } - if ($entryisselected) $result[$akey] = $bib; - } - if (array_key_exists( Q_BIBLIOGRAPHY, $query )) { - ksort($result); // a bibliography is sorted in ascending order - } else { - krsort($result); - } - - return $result; + } + if ($entryisselected) { + if ($field==Q_BIBLIOGRAPHY) { + $akey = $citations[$bib->getKey()]; + } else { + $akey = count($result)+1; + } + $result[$akey] = $bib; + } + } + + return $result; } } // end class -/* returns the default embedded CSS of bibtexbrowser */ +/** returns the default CSS of bibtexbrowser */ function bibtexbrowserDefaultCSS() { ?> @@ -2931,7 +3097,13 @@ function bibtexbrowserDefaultCSS() { text-align: right; } -.header { +.btb-header { + background-color: #995124; + color: #FFFFFF; + padding: 1px 2px 1px 2px; +} + +.btb-nav-title { background-color: #995124; color: #FFFFFF; padding: 1px 2px 1px 2px; @@ -3007,27 +3179,37 @@ 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; } .bibentry-abstract { margin:15px; } .bibentry-label { margin-top:15px; } .bibentry-reference { margin-bottom:15px; padding:10px; background: none repeat scroll 0 0 #F5F5F5; border: 1px solid #DDDDDD; } +.btb-nav { text-align: right; } and TITLE */ +/** encapsulates the content of a delegate into full-fledged HTML (<HTML><BODY> and TITLE) +usage: +
        +  $db = zetDB('metrics.bib');
        +  $dis = new BibEntryDisplay($db->getEntryByKey('Schmietendorf2000'));
        +  new HTMLWrapper($dis);
        +
        +*/ class HTMLWrapper { /** * $content: an object with methods display() getRSS() - formatedHeader() getTitle() * $title: title of the page */ @@ -3042,8 +3224,10 @@ echo ' - -getRSS()!='') echo ''; ?> + +getRSS()!='') echo ''; +?> '.strip_tags($content->getTitle()).''; - +if (method_exists($content, 'getTitle')) { + echo ''.strip_tags($content->getTitle()).''; +} + // now the CSS echo ''; ?> -formatedHeader();?> -display();?> +" . $content->getTitle() . ""; +} +?> +display(); + echo poweredby(); + + if (BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT) { + javascript(); + } + + +?> '; } -/** NoWrapper calls method display() on the content. */ +/** does nothing but calls method display() on the content. +usage: +
        +  $db = zetDB('metrics.bib');
        +  $dis = new SimpleDisplay($db);
        +  new NoWrapper($dis);
        +
        +*/ class NoWrapper { function NoWrapper(&$content) { - @header('Content-type: text/html; charset='.ENCODING); echo $content->display(); } } -/** is used to create an subset of a bibtex file */ +/** is used to create an subset of a bibtex file. +usage: +
        +  $db = zetDB('metrics.bib');
        +  $query = array('year'=>2005);
        +  $dis = new BibtexDisplay()->setEntries($db->multisearch($query));
        +  $dis->display();
        +
        +*/ class BibtexDisplay { - /** an array of BibEbtry */ - var $results; - - /** the initial query to get the results */ - var $query; + function BibtexDisplay() {} + + function setTitle($title) { $this->title = $title; return $this; } - function BibtexDisplay(&$results, &$query) { - $this->results=$results; - $this->query=$query; + /** sets the entries to be shown */ + function setEntries(&$entries) { + $this->entries = $entries; } + function setWrapper($x) { $x->wrapper = 'NoWrapper'; } + function display() { header('Content-type: text/plain; charset='.ENCODING); - echo '% '.query2title($this->query)."\n"; + echo '% generated by bibtexbrowser '."\n"; + echo '% '.@$this->title."\n"; echo '% Encoding: '.ENCODING."\n"; - foreach($this->results as $bibentry) { echo $bibentry->getText()."\n"; } + foreach($this->entries as $bibentry) { echo $bibentry->getText()."\n"; } exit; } } -/** is used to create an RSS feed */ -class RSSDisplay { +/** creates paged output, e.g: [[http://localhost/bibtexbrowser/testPagedDisplay.php?page=1]] +usage: +
        +  $_GET['library']=1;
        +  include( 'bibtexbrowser.php' );
        +  $db = zetDB('metrics.bib');
        +  $pd = new PagedDisplay();
        +  $pd->setEntries($db->bibdb);
        +  $pd->display();
        +
        +*/ +class PagedDisplay { + + var $query = array(); + + function PagedDisplay() { + $this->setPage(); + } + + /** sets the entries to be shown */ + function setEntries(&$entries) { + uasort($entries, ORDER_FUNCTION); + $this->entries = array_values($entries); + } + + /** sets $this->page from $_GET, defaults to 1 */ + function setPage() { + $this->page = 1; + if (isset($_GET['page'])) { + $this->page = $_GET['page']; + } + } + + function setQuery($query = array()) { + $this->query = $query; + } + + function getTitle() { + return query2title($this->query). ' - page '.$this->page; + } + + function display() { + $less = false; + + if ($this->page>1) {$less = true;} + + $more = true; + + // computing $more + $index = ($this->page)*PAGE_SIZE; + if (!isset($this->entries[$index])) { + $more = false; + } + + $this->menu($less, $more); + layoutHeaderHTML(); + for ($i = 0; $i < PAGE_SIZE; $i++) { + $index = ($this->page-1)*PAGE_SIZE + $i; + if (isset($this->entries[$index])) { + $bib = $this->entries[$index]; + $bib->toHTML(); + + } else { + //break; + } + } // end foreach + layoutFooterHTML(); + + $this->menu($less, $more); + } + + function menu($less, $more) { + + echo ''; + + $prev = $this->query; + $prev['page'] = $this->page-1; + if ($less == true) { echo 'Prev Page'; } + + if ($less && $more) { echo ' | '; } + + $next = $this->query; + $next['page'] = $this->page+1; + if ($more == true) { echo 'Next Page'; } + echo ''; - /** an array of BibEbtry */ - var $results; + } +} - /** the initial query to get the results */ - var $query; +/** is used to create an RSS feed. +usage: +
        +  $db = zetDB('metrics.bib');
        +  $query = array('year'=>2005);
        +  $rss = new RSSDisplay();
        +  $entries = $db->getLatestEntries(10);
        +  $rss->setEntries($entries);
        +  $rss->display();
        +
        +*/ +class RSSDisplay { - function RSSDisplay(&$results, &$query) { - $this->results=$results; - $this->query=$query; - $this->title = query2title($query); + var $title = 'RSS produced by bibtexbrowser'; + + function RSSDisplay() { + // nothing by default } + function setTitle($title) { $this->title = $title; return $this; } + /** tries to always output a valid XML/RSS string * based on ENCODING, HTML tags, and the transformations * that happened in latex2html */ @@ -3155,7 +3468,13 @@ class RSSDisplay { return $desc; } - + /** sets the entries to be shown */ + function setEntries(&$entries) { + $this->entries = $entries; + } + + function setWrapper($x) { $x->wrapper = 'NoWrapper'; } + function display() { header('Content-type: application/rss+xml'); echo ''; @@ -3168,10 +3487,10 @@ class RSSDisplay { http:// - bibtexbrowser v20111211 + bibtexbrowser v20130226 results as $bibentry) { + foreach($this->entries as $bibentry) { ?> <?php echo $this->text2rss($bibentry->getTitle());?> @@ -3183,7 +3502,7 @@ class RSSDisplay { echo $this->text2rss(bib2html($bibentry)."\n".$bibentry->getAbstract()); ?> - getKey());?> + getKey());?> @@ -3196,26 +3515,36 @@ class RSSDisplay { - +/** is responsible for transforming a query string of $_GET[..] into a publication list. +usage: +
        +  $_GET['library']=1;
        +  @require('bibtexbrowser.php');
        +  // simulating ?bib=metrics.bib&year=2009
        +  $_GET['bib']='metrics.bib';
        +  $_GET['year']='2006';
        +  $x = new Dispatcher();
        +  $x->main();
        +
        +*/ class Dispatcher { /** this is the query */ var $query = array(); - /** this is the result of the querw: an array of BibEbtry */ - var $selectedEntries = array(); - - /** the displayer of selected entries. The default is a paged display. + /** the displayer of selected entries. The default is set in BIBTEXBROWSER_DEFAULT_DISPLAY. * It could also be an RSSDisplay if the rss keyword is present */ - var $displayer = 'PagedDisplay'; + var $displayer = ''; /** the wrapper of selected entries. The default is an HTML wrapper * It could also be a NoWrapper when you include your pub list in your home page */ 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'])) { @@ -3226,12 +3555,12 @@ 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) // realpath is required if the path contains sym-linked directories (bug found by Mark Hereld) - if (strtr(realpath(__FILE__),"\\","/")!=strtr(realpath($_SERVER['SCRIPT_FILENAME']),"\\","/")) $this->wrapper='NoWrapper'; + if (strtr(realpath(__FILE__),"\\","/")!=strtr(realpath($_SERVER['SCRIPT_FILENAME']),"\\","/")) $this->wrapper=BIBTEXBROWSER_EMBEDDED_WRAPPER; // first pass, we will exit if we encounter key or menu or academic // other wise we just create the $this->query @@ -3242,6 +3571,8 @@ class Dispatcher { } } + // at this point, we may have a query + if (count($this->query)>0) { // first test for inconsistent queries @@ -3250,11 +3581,52 @@ class Dispatcher { unset($this->query[Q_ALL]); } - $this->selectedEntries = $_GET[Q_DB]->multisearch($this->query); + $selectedEntries = $_GET[Q_DB]->multisearch($this->query); + + if (count($selectedEntries)==0) { + $this->displayer = 'NotFoundDisplay'; + } + + // default order + //uasort($selectedEntries, ORDER_FUNCTION); + //$selectedEntries = array_values($selectedEntries); + + //echo '
        ';print_r($selectedEntries);echo '
        '; + + + if ($this->displayer=='') { + $this->displayer = BIBTEXBROWSER_DEFAULT_DISPLAY; + } + } // otherwise the query is left empty + + // 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')) { + $x->setEntries($selectedEntries); + } + + if (method_exists($x,'setTitle')) { + $x->setTitle(query2title($this->query)); + } + + if (method_exists($x,'setQuery')) { + $x->setQuery($this->query); + } - // required for PHP4 to have this intermediate variable - $x = new $this->displayer($this->selectedEntries,$this->query); - new $this->wrapper($x); + // should call method display() on $x + new $this->wrapper($x); + + $this->clearQuery(); } else { // we send a redirection for having the frameset @@ -3266,10 +3638,20 @@ class Dispatcher { } } + /** clears the query string in $_GET so that bibtexbrowser can be called multiple times */ + function clearQuery() { + $params= array(Q_ALL,'rss', 'astext', Q_SEARCH, Q_EXCLUDE, Q_YEAR, EDITOR, Q_TAG, Q_AUTHOR, Q_TYPE, Q_ACADEMIC, Q_KEY); + foreach($params as $p) { unset($_GET[$p]); } + } + function all() { $this->query[Q_ALL]=1; } + function display() { + $this->displayer=$_GET['display']; + } + function rss() { $this->displayer='RSSDisplay'; $this->wrapper='NoWrapper'; @@ -3287,42 +3669,35 @@ class Dispatcher { $this->query[Q_SEARCH]=$_GET[Q_SEARCH]; } - function bibliography() { - $this->displayer='BibliographyDisplay'; - if (preg_match('/utf-?8/i',ENCODING)) { - $_GET[Q_BIBLIOGRAPHY] = json_decode($_GET[Q_BIBLIOGRAPHY]); - } - $this->query[Q_BIBLIOGRAPHY]=$_GET[Q_BIBLIOGRAPHY]; - } - function exclude() { $this->query[Q_EXCLUDE]=$_GET[Q_EXCLUDE]; } - function year() { $this->query[Q_YEAR]=$_GET[Q_YEAR]; } + function year() { + // we may want the latest + if ($_GET[Q_YEAR]=='latest') { + $years = $_GET[Q_DB]->yearIndex(); + $_GET[Q_YEAR]=array_shift($years); + } + $this->query[Q_YEAR]=$_GET[Q_YEAR]; + } function editor() { $this->query[EDITOR]=$_GET[EDITOR]; } function keywords() { $this->query[Q_TAG]=$_GET[Q_TAG]; } - function layout() { print $_GET[LAYOUT]; $this->query[LAYOUT]=$_GET[LAYOUT]; } // added by MG - 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]; } function menu() { - $menu = new MenuManager($_GET[Q_DB]); + $menu = createMenuManager(); + $menu->setDB($_GET[Q_DB]); new $this->wrapper($menu,array(array('robots','noindex'))); return 'END_DISPATCH'; } @@ -3350,13 +3725,32 @@ class Dispatcher { function key() { if ($_GET[Q_DB]->contains($_GET[Q_KEY])) { - $bibdisplay = new BibEntryDisplay($_GET[Q_DB]->getEntryByKey($_GET[Q_KEY])); - new $this->wrapper($bibdisplay,$bibdisplay->metadata()); + $bibentry = $_GET[Q_DB]->getEntryByKey($_GET[Q_KEY]); + $entries = array($bibentry); + if (isset($_GET['astext'])) { + $bibdisplay = new BibtexDisplay(); + $bibdisplay->setEntries($entries); + $bibdisplay->display(); + } else { + $bibdisplay = createBibEntryDisplay(); + $bibdisplay->setEntries($entries); + new $this->wrapper($bibdisplay,$bibdisplay->metadata()); + } return 'END_DISPATCH'; } - else { new NonExistentBibEntryError(); } + else { nonExistentBibEntryError(); } + } + + function bibliography() { + $this->displayer='BibliographyDisplay'; + if (preg_match('/utf-?8/i',ENCODING)) { + $_GET[Q_BIBLIOGRAPHY] = json_decode($_GET[Q_BIBLIOGRAPHY]); + } + $this->query[Q_BIBLIOGRAPHY]=$_GET[Q_BIBLIOGRAPHY]; } + function layout() { $this->query[LAYOUT]=$_GET[LAYOUT]; } + function keys() { if (preg_match('/utf-?8/i',ENCODING)) { // Create array from list of bibtex entries @@ -3369,7 +3763,7 @@ class Dispatcher { function diagnosis() { header('Content-type: text/plain'); echo "php version: ".phpversion()."\n"; - echo "bibtexbrowser version: 20111211\n"; + echo "bibtexbrowser version: 20130226\n"; echo "dir: ".decoct(fileperms(dirname(__FILE__)))."\n"; echo "bibtex file: ".decoct(fileperms($_GET[Q_FILE]))."\n"; exit; @@ -3381,25 +3775,26 @@ class Dispatcher { - + You are browsing <?php echo $_GET[Q_FILE]; ?> with bibtexbrowser - + main(); ?> - From a69853d7b15226df49bb77999f843d78fdd10f37 Mon Sep 17 00:00:00 2001 From: Matthieu Guillaumin Date: Wed, 27 Feb 2013 09:33:21 +0100 Subject: [PATCH 4/8] simplified code by using Q_KEYS for Q_BIBLIOGRAPHY; improve btb.bibliography.php --- ...aphy.php => bibtexbrowser.bibliography.php | 24 +++++++++- bibtexbrowser.local.php | 6 +-- bibtexbrowser.php | 45 ++++++++----------- 3 files changed, 42 insertions(+), 33 deletions(-) rename bibtexbrowser_bibliography.php => bibtexbrowser.bibliography.php (55%) diff --git a/bibtexbrowser_bibliography.php b/bibtexbrowser.bibliography.php similarity index 55% rename from bibtexbrowser_bibliography.php rename to bibtexbrowser.bibliography.php index 8cdbc30..97902e2 100644 --- a/bibtexbrowser_bibliography.php +++ b/bibtexbrowser.bibliography.php @@ -1,5 +1,11 @@ $ref ) { + $keylist["$ref"] = $entry; // make sure keys are strings + } + return json_encode($keylist) ; +} + +function make_bibliography() { + global $_GET; + $_GET = array(); + $_GET['bib']='mg.bib'; + $_GET['bibliography']=1; + $_GET['keys']=make_bibtexbrowser_bibliography_keys(); + include( 'bibtexbrowser.php' ); } ?> diff --git a/bibtexbrowser.local.php b/bibtexbrowser.local.php index 3b45ff3..5e017a7 100644 --- a/bibtexbrowser.local.php +++ b/bibtexbrowser.local.php @@ -138,17 +138,13 @@ class BibliographyDisplay { /** Displays a set of bibtex entries in an HTML table */ function display() { - ksort($this->entries); //, ORDER_FUNCTION); + ksort($this->entries); // sort the keys, not the values layoutHeaderHTML(); - - $count = count($this->entries); - $i=0; foreach ($this->entries as $ref => $bib) { $bib->setIndex($ref); $bib->toHTML(); } // end foreach - layoutFooterHTML(); } // end function diff --git a/bibtexbrowser.php b/bibtexbrowser.php index 8b549cd..e5d8c14 100644 --- a/bibtexbrowser.php +++ b/bibtexbrowser.php @@ -100,12 +100,12 @@ define('BIBTEXBROWSER','v20130206'); @define('Q_ALL', 'all'); @define('Q_ENTRY', 'entry'); @define('Q_KEY', 'key'); -@define('Q_KEYS', 'keys'); // select entries using a list of bibtex entries +@define('Q_KEYS', 'keys'); // select entries using a JSON array of bibtex keys (if an associative array is used, the keys of this array are used as item abbrv) @define('Q_SEARCH', 'search'); -@define('Q_BIBLIOGRAPHY', 'bibliography'); // select entries and their index using a JSON associative array @define('Q_EXCLUDE', 'exclude'); @define('Q_RESULT', 'result'); @define('Q_ACADEMIC', 'academic'); +@define('Q_BIBLIOGRAPHY', 'bibliography'); @define('Q_DB', 'bibdb'); @define('Q_LATEST', 'latest'); @define('AUTHOR', 'author'); @@ -2999,23 +2999,25 @@ class BibDataBase { if (count($query)<1) {return array();} if (isset($query[Q_ALL])) return array_values($this->bibdb); - if (array_key_exists( Q_BIBLIOGRAPHY, $query )) { - $citations = array(); - foreach ($query[Q_BIBLIOGRAPHY] as $key => $value) { - $citations[$key] = $value; - } - } if (array_key_exists( Q_KEYS, $query )) { - $citations = array(); - foreach ($query[Q_KEYS] as $id => $key) { - $citations[] = $key; + $keylist = array(); + $is_assoc = (bool)count(array_filter(array_keys($query[Q_KEYS]), 'is_string')); + foreach ($query[Q_KEYS] as $ref => $key) { + if ($is_assoc) { + $keylist[$ref] = $key; + } else { + $keylist[] = $key; + } } + } else { + $is_assoc = false; } $result = array(); foreach ($this->bibdb as $bib) { $entryisselected = true; + $akey = -1; foreach ($query as $field => $fragment) { $field = strtolower($field); if ($field==Q_SEARCH) { @@ -3042,14 +3044,11 @@ class BibDataBase { break; } } - else if ($field==Q_BIBLIOGRAPHY) { - if ( !array_key_exists( $bib->getKey(), $citations ) ) { - $entryisselected = false; - break; - } - } else if ($field==Q_KEYS) { - if ( ! in_array( $bib->getKey(), $citations ) ) { + if ( ! in_array( $bib->getKey(), $keylist ) ) { + if ($is_assoc) { + $akey = array_search( $bib->getKey(), $keylist ); + } $entryisselected = false; break; } @@ -3063,9 +3062,7 @@ class BibDataBase { } if ($entryisselected) { - if ($field==Q_BIBLIOGRAPHY) { - $akey = $citations[$bib->getKey()]; - } else { + if ($akey<0) { $akey = count($result)+1; } $result[$akey] = $bib; @@ -3743,10 +3740,6 @@ class Dispatcher { function bibliography() { $this->displayer='BibliographyDisplay'; - if (preg_match('/utf-?8/i',ENCODING)) { - $_GET[Q_BIBLIOGRAPHY] = json_decode($_GET[Q_BIBLIOGRAPHY]); - } - $this->query[Q_BIBLIOGRAPHY]=$_GET[Q_BIBLIOGRAPHY]; } function layout() { $this->query[LAYOUT]=$_GET[LAYOUT]; } @@ -3754,7 +3747,7 @@ class Dispatcher { function keys() { if (preg_match('/utf-?8/i',ENCODING)) { // Create array from list of bibtex entries - $_GET[Q_KEYS] = array_filter(explode(',',strtr($_GET[Q_KEYS]," ",",")),'strlen'); + $_GET[Q_KEYS] = json_decode($_GET[Q_KEYS]); } $this->query[Q_KEYS]=$_GET[Q_KEYS]; } From 3abf3f0b9b60e020cc4cc76cae4d051f25d07802 Mon Sep 17 00:00:00 2001 From: Matthieu Guillaumin Date: Wed, 27 Feb 2013 11:04:29 +0100 Subject: [PATCH 5/8] introduced Q_ASSOCKEYS and improves Q_KEYS and Q_BIBLIOGRAPHY --- bibtexbrowser.bibliography.php | 14 +++++----- bibtexbrowser.local.php | 14 +++------- bibtexbrowser.php | 47 +++++++++++++++++++--------------- 3 files changed, 35 insertions(+), 40 deletions(-) diff --git a/bibtexbrowser.bibliography.php b/bibtexbrowser.bibliography.php index 97902e2..61040e6 100644 --- a/bibtexbrowser.bibliography.php +++ b/bibtexbrowser.bibliography.php @@ -1,6 +1,7 @@ , one can cite +/* Example: As shown in , one can use bibtex within HTML/PHP. */ function cite() { global $citations; @@ -38,19 +39,16 @@ function cite() { // prepare bibtexbrowser query function make_bibtexbrowser_bibliography_keys() { global $citations; - $keylist = array(); - foreach ( $citation as $entry => $ref ) { - $keylist["$ref"] = $entry; // make sure keys are strings - } - return json_encode($keylist) ; + return json_encode(array_flip($citations)) ; } function make_bibliography() { global $_GET; $_GET = array(); $_GET['bib']='mg.bib'; - $_GET['bibliography']=1; + $_GET['bibliography']=1; // sets assoc_keys $_GET['keys']=make_bibtexbrowser_bibliography_keys(); + //print_r($_GET); include( 'bibtexbrowser.php' ); } diff --git a/bibtexbrowser.local.php b/bibtexbrowser.local.php index 5e017a7..1f68dbf 100644 --- a/bibtexbrowser.local.php +++ b/bibtexbrowser.local.php @@ -119,38 +119,30 @@ function MGBibliographyStyle(&$bibentry) { $result .= '
        '; return $result; -} +} // end style function /** Class to display a bibliography of a page. */ class BibliographyDisplay { - function setDB(&$bibdatabase) { - $this->setEntries($bibdatabase->bibdb); - } + function setDB(&$bibdatabase) { $this->setEntries($bibdatabase->bibdb); } /** sets the entries to be shown */ - function setEntries(&$entries) { - $this->entries = $entries; - } + function setEntries(&$entries) { $this->entries = $entries; } function setTitle($title) { $this->title = $title; return $this; } function getTitle() { return @$this->title ; } /** Displays a set of bibtex entries in an HTML table */ function display() { - ksort($this->entries); // sort the keys, not the values - layoutHeaderHTML(); foreach ($this->entries as $ref => $bib) { $bib->setIndex($ref); $bib->toHTML(); } // end foreach layoutFooterHTML(); - } // end function } // end class - ?> diff --git a/bibtexbrowser.php b/bibtexbrowser.php index e5d8c14..2521ed5 100644 --- a/bibtexbrowser.php +++ b/bibtexbrowser.php @@ -100,7 +100,8 @@ define('BIBTEXBROWSER','v20130206'); @define('Q_ALL', 'all'); @define('Q_ENTRY', 'entry'); @define('Q_KEY', 'key'); -@define('Q_KEYS', 'keys'); // select entries using a JSON array of bibtex keys (if an associative array is used, the keys of this array are used as item abbrv) +@define('Q_KEYS', 'keys'); // select entries using a JSON array of bibtex keys +@define('Q_ASSOCKEYS', 'assoc_keys'); // consider Q_KEYS as an associative array, and use the keys of Q_KEYS as item abbrv @define('Q_SEARCH', 'search'); @define('Q_EXCLUDE', 'exclude'); @define('Q_RESULT', 'result'); @@ -3000,24 +3001,21 @@ class BibDataBase { if (isset($query[Q_ALL])) return array_values($this->bibdb); if (array_key_exists( Q_KEYS, $query )) { - $keylist = array(); - $is_assoc = (bool)count(array_filter(array_keys($query[Q_KEYS]), 'is_string')); - foreach ($query[Q_KEYS] as $ref => $key) { - if ($is_assoc) { - $keylist[$ref] = $key; - } else { - $keylist[] = $key; - } - } + $keylist = (array) $query[Q_KEYS]; + $reflist = array_flip($keylist); + $is_assoc = array_key_exists( Q_ASSOCKEYS, $query ); //array_values($query[Q_KEYS]) !== $query[Q_KEYS]; + //if ($is_assoc) echo "Assoc"; + //print_r($keylist); } else { $is_assoc = false; } + unset($query[Q_ASSOCKEYS]); // not used for filtering the bibtex entries $result = array(); foreach ($this->bibdb as $bib) { $entryisselected = true; - $akey = -1; + $akey = ''; foreach ($query as $field => $fragment) { $field = strtolower($field); if ($field==Q_SEARCH) { @@ -3046,12 +3044,11 @@ class BibDataBase { } else if ($field==Q_KEYS) { if ( ! in_array( $bib->getKey(), $keylist ) ) { - if ($is_assoc) { - $akey = array_search( $bib->getKey(), $keylist ); - } + //echo $bib->getKey() . " not in list
        \n"; $entryisselected = false; break; - } + } + //echo $bib->getKey() . " in list
        \n"; } else { if (!$bib->hasPhrase($fragment, $field)) { @@ -3062,13 +3059,16 @@ class BibDataBase { } if ($entryisselected) { - if ($akey<0) { - $akey = count($result)+1; + if ( $is_assoc ) { + $result[$reflist[$bib->getKey()]] = $bib; + } else { + $result[] = $bib; } - $result[$akey] = $bib; - } + } else { + //echo "entry ".$bib->getKey()." not selected\n"; + } } - + //foreach ($result as $ref=>$bib) {echo $ref." => ".$bib->getKey()." ";} return $result; } } // end class @@ -3739,7 +3739,8 @@ class Dispatcher { } function bibliography() { - $this->displayer='BibliographyDisplay'; + $this->displayer='BibliographyDisplay'; + $this->query[Q_ASSOCKEYS]=1; } function layout() { $this->query[LAYOUT]=$_GET[LAYOUT]; } @@ -3752,6 +3753,10 @@ class Dispatcher { $this->query[Q_KEYS]=$_GET[Q_KEYS]; } + function assoc_keys() { + $this->query[Q_ASSOCKEYS]=$_GET[Q_ASSOCKEYS]; + } + /** is used to remotely analyzed a situation */ function diagnosis() { header('Content-type: text/plain'); From 240c3a851d8d28f2416ff59312f533a0c9d31845 Mon Sep 17 00:00:00 2001 From: Matthieu Guillaumin Date: Wed, 27 Feb 2013 14:09:14 +0100 Subject: [PATCH 6/8] fixes #1. the ICONS constant is provided as a json-encoded associative array. also added JsWrapper for javascript enhancement for embedded bibtexbrowser --- bibtexbrowser.local.php | 13 +++++++++++++ bibtexbrowser.php | 16 ++++++++-------- 2 files changed, 21 insertions(+), 8 deletions(-) diff --git a/bibtexbrowser.local.php b/bibtexbrowser.local.php index 1f68dbf..12a6f77 100644 --- a/bibtexbrowser.local.php +++ b/bibtexbrowser.local.php @@ -4,6 +4,18 @@ @define('USEBIBTHUMBNAIL',0); @define('BIBTHUMBNAIL','thumbnail'); +/** does nothing but calls method display() on the content and use javascript if needed. +*/ +class JsWrapper { + function JsWrapper(&$content) { + echo $content->display(); + if (BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT) { + javascript(); + } + } +} + + function MGBibliographyStyle(&$bibentry) { $title = $bibentry->getTitle(); $type = $bibentry->getType(); @@ -144,5 +156,6 @@ class BibliographyDisplay { } // end class + ?> diff --git a/bibtexbrowser.php b/bibtexbrowser.php index 2521ed5..a41c621 100644 --- a/bibtexbrowser.php +++ b/bibtexbrowser.php @@ -122,6 +122,8 @@ define('BIBTEXBROWSER','v20130206'); @define('METADATA_EPRINTS',false); @define('LAYOUT','table'); // may be table/list/deflist. defines the HTML rendering options (,
          ,
          , resp.). 'list' only works with 'ABBRV_TYPE'='index'. +@define('ICONS','[]'); +@define('Q_ICONS','icons'); // in embedded mode, we still need a URL for displaying bibtex entries alone // this is usually resolved to bibtexbrowser.php @@ -153,6 +155,7 @@ See also zetDB(). function setDB() { list($db, $parsed, $updated, $saved) = _zetDB(@$_GET[Q_FILE]); $_GET[Q_DB] = $db; + $_GET[Q_ICONS] = (array) json_decode(ICONS); return $updated; } @@ -1055,17 +1058,15 @@ class BibEntry { } /** replace [$ext] with an icon whose url is defined in a string - * e.g. getIconOrTxt('pdf') will show the icon defined by @string{icon_pdf=""} or print '[pdf]' - * or getIconOrTxt('pdf','paper') will show the icon defined by @string{icon_pdf=""} or print '[paper]' + * e.g. getIconOrTxt('pdf') will show the icon defined in $_GET[Q_ICONS]['pdf'] or print '[pdf]' + * or getIconOrTxt('pdf','paper') will show the icon defined by $_GET[Q_ICONS]['pdf'] or print '[paper]' * The replacement text is also used if the url does not point to a valid file (using the "alt" property of the "img" html tag) - * Warning: by convention @string are case sensitive */ function getIconOrTxt($ext,$def=NULL) { - // e.g. @STRING{icon_pdf="http://mywebsite/pdf.png"} if ($def==NULL) { $def=$ext; } - $stringkey = strtolower('icon_'.$ext); - if (isset($_GET[Q_DB]->stringdb[$stringkey])){ - $str='['.$def.']'; + $icons = $_GET[Q_ICONS]; + if ( array_key_exists($ext,$icons) ) { + $str='['.$def.']'; } else { $str='['.$def.']'; } @@ -2419,7 +2420,6 @@ class SimpleDisplay { } // end foreach layoutFooterHTML(); - } // end function } // end class From 58900ff73b43d3731b9b62ff24e77d7bc200cf1b Mon Sep 17 00:00:00 2001 From: Matthieu Guillaumin Date: Wed, 27 Feb 2013 15:21:44 +0100 Subject: [PATCH 7/8] fixes #2. the only limitation is LAYOUT=list works only with ABBRV_TYPE=index. --- bibtexbrowser.bibliography.php | 59 ++++++++++++++++++++-------------- 1 file changed, 35 insertions(+), 24 deletions(-) diff --git a/bibtexbrowser.bibliography.php b/bibtexbrowser.bibliography.php index 61040e6..bcd8a02 100644 --- a/bibtexbrowser.bibliography.php +++ b/bibtexbrowser.bibliography.php @@ -1,17 +1,20 @@ ?"; } return '' . $a . '' ; } @@ -20,34 +23,42 @@ function linkify($a) { */ function cite() { global $citations; + global $DB; $entries = func_get_args(); // list of bibtex entries $refs = array(); // corresponding references foreach ($entries as $entry) { - if ( array_key_exists ( $entry , $citations ) ) { - $ref = $citations[$entry] ; - } else { - $ref = count( $citations ) + 1 ; - $citations[$entry] = $ref ; - } - $refs[] = $ref; + $bib = $DB->getEntryByKey($entry); + if ( empty($bib) ) { + $ref = array(); // empty ref for detection by linkify, while getting last with sort() + $refs[] = $ref; + continue; + } + if (ABBRV_TYPE != 'index') { + $ref = $bib->getAbbrv(); + $citations[$entry] = $ref; + } else { + if ( array_key_exists ( $entry , $citations ) ) { + $ref = $citations[$entry] ; + } else { + $ref = count( $citations ) + 1 ; + $citations[$entry] = $ref ; + } + } + $refs[] = $ref; } sort( $refs ); $links = array_map( 'linkify', $refs ); echo "[" . implode(",",$links) . "]" ; } -// prepare bibtexbrowser query -function make_bibtexbrowser_bibliography_keys() { - global $citations; - return json_encode(array_flip($citations)) ; -} - +// Function to print out the table/list of references function make_bibliography() { - global $_GET; + global $citations; + $bibfile = $_GET[Q_FILE]; // save bibfilename before resetting $_GET $_GET = array(); - $_GET['bib']='mg.bib'; - $_GET['bibliography']=1; // sets assoc_keys - $_GET['keys']=make_bibtexbrowser_bibliography_keys(); + $_GET['bib'] = $bibfile; + $_GET['bibliography']=1; // also sets $_GET['assoc_keys']=1 + $_GET['keys'] = json_encode(array_flip($citations)); //print_r($_GET); include( 'bibtexbrowser.php' ); } From 352886011bca3b1297b1f180391abee507924164 Mon Sep 17 00:00:00 2001 From: Matthieu Guillaumin Date: Thu, 7 Mar 2013 17:01:09 +0100 Subject: [PATCH 8/8] added veryCompactAuthors and very short author+title as reference abbr. also added javascript highlighting of clicked citation --- bibtexbrowser.bibliography.php | 34 ++++++++++++++++++++++++++-------- bibtexbrowser.php | 10 ++++++++++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/bibtexbrowser.bibliography.php b/bibtexbrowser.bibliography.php index bcd8a02..591afbc 100644 --- a/bibtexbrowser.bibliography.php +++ b/bibtexbrowser.bibliography.php @@ -13,9 +13,9 @@ $DB = load_DB(); $citations = array(); // Function to create a link for a bibtex entry -function linkify($a) { - if ( empty($a) ) { return "?"; } - return '' . $a . '' ; +function linkify($txt,$a) { + if ( empty($a) ) { return '?'; } + return '' . $a . '' ; } // Create citations from bibtex entries. One argument per bibtex entry. @@ -30,7 +30,8 @@ function cite() { $bib = $DB->getEntryByKey($entry); if ( empty($bib) ) { $ref = array(); // empty ref for detection by linkify, while getting last with sort() - $refs[] = $ref; + $txt = "Unknown key «$entry»"; + $refs[$txt] = $ref; continue; } if (ABBRV_TYPE != 'index') { @@ -44,10 +45,14 @@ function cite() { $citations[$entry] = $ref ; } } - $refs[] = $ref; + $txt = $bib->getVeryCompactedAuthors() . ", «" . $bib->getTitle() . "», " . $bib->getYear() ; + $refs[$txt] = $ref; + } + asort( $refs ); + $links = array(); + foreach ( $refs as $txt => $ref ) { + $links[] = linkify($txt,$ref); } - sort( $refs ); - $links = array_map( 'linkify', $refs ); echo "[" . implode(",",$links) . "]" ; } @@ -57,10 +62,23 @@ function make_bibliography() { $bibfile = $_GET[Q_FILE]; // save bibfilename before resetting $_GET $_GET = array(); $_GET['bib'] = $bibfile; - $_GET['bibliography']=1; // also sets $_GET['assoc_keys']=1 + $_GET['bibliography'] = 1; // also sets $_GET['assoc_keys']=1 $_GET['keys'] = json_encode(array_flip($citations)); //print_r($_GET); include( 'bibtexbrowser.php' ); +?> + + diff --git a/bibtexbrowser.php b/bibtexbrowser.php index a41c621..1d3e6e7 100644 --- a/bibtexbrowser.php +++ b/bibtexbrowser.php @@ -1252,6 +1252,16 @@ class BibEntry { return $this->formatAuthor($authors[0]) . $etal; } + /** + * Returns a compacted string form of author names by throwing away + * all author names except for the first one and appending ", et al." + */ + function getVeryCompactedAuthors(){ + $authors = $this->getRawAuthors(); + $etal = count($authors) > 1 ? ', et al.' : ''; + list($firstname, $lastname) = splitFullName($authors[0]); + return $lastname . $etal; + } /** add the link to the homepage if it is defined in a string * e.g. @string{hp_MartinMonperrus="http://www.monperrus.net/martin"}