From 74cb778193ade2eab61e409d463641040fee97d9 Mon Sep 17 00:00:00 2001 From: Matthieu Guillaumin Date: Tue, 26 Feb 2013 17:22:15 +0100 Subject: [PATCH] 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) ; +} + +?>