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