diff --git a/bibtexbrowser.bibliography.php b/bibtexbrowser.bibliography.php
new file mode 100644
index 0000000..591afbc
--- /dev/null
+++ b/bibtexbrowser.bibliography.php
@@ -0,0 +1,84 @@
+?'; }
+ return '' . $a . '' ;
+}
+
+// Create citations from bibtex entries. One argument per bibtex entry.
+/* Example: As shown in , one can use bibtex within HTML/PHP.
+*/
+function cite() {
+ global $citations;
+ global $DB;
+ $entries = func_get_args(); // list of bibtex entries
+ $refs = array(); // corresponding references
+ foreach ($entries as $entry) {
+ $bib = $DB->getEntryByKey($entry);
+ if ( empty($bib) ) {
+ $ref = array(); // empty ref for detection by linkify, while getting last with sort()
+ $txt = "Unknown key «$entry»";
+ $refs[$txt] = $ref;
+ continue;
+ }
+ if (ABBRV_TYPE != 'index') {
+ $ref = $bib->getAbbrv();
+ $citations[$entry] = $ref;
+ } else {
+ if ( array_key_exists ( $entry , $citations ) ) {
+ $ref = $citations[$entry] ;
+ } else {
+ $ref = count( $citations ) + 1 ;
+ $citations[$entry] = $ref ;
+ }
+ }
+ $txt = $bib->getVeryCompactedAuthors() . ", «" . $bib->getTitle() . "», " . $bib->getYear() ;
+ $refs[$txt] = $ref;
+ }
+ asort( $refs );
+ $links = array();
+ foreach ( $refs as $txt => $ref ) {
+ $links[] = linkify($txt,$ref);
+ }
+ echo "[" . implode(",",$links) . "]" ;
+}
+
+// Function to print out the table/list of references
+function make_bibliography() {
+ global $citations;
+ $bibfile = $_GET[Q_FILE]; // save bibfilename before resetting $_GET
+ $_GET = array();
+ $_GET['bib'] = $bibfile;
+ $_GET['bibliography'] = 1; // also sets $_GET['assoc_keys']=1
+ $_GET['keys'] = json_encode(array_flip($citations));
+ //print_r($_GET);
+ include( 'bibtexbrowser.php' );
+?>
+
+
diff --git a/bibtexbrowser.local.php b/bibtexbrowser.local.php
new file mode 100644
index 0000000..12a6f77
--- /dev/null
+++ b/bibtexbrowser.local.php
@@ -0,0 +1,161 @@
+display();
+ if (BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT) {
+ javascript();
+ }
+ }
+}
+
+
+function MGBibliographyStyle(&$bibentry) {
+ $title = $bibentry->getTitle();
+ $type = $bibentry->getType();
+
+ // later on, all values of $entry will be joined by a comma
+ $entry=array();
+
+
+ // thumbnail
+ if (USEBIBTHUMBNAIL && $bibentry->hasField(BIBTHUMBNAIL)) {
+ $thumb = '';}
+ else $thumb = '';
+
+ // title
+ // usually in bold: .bibtitle { font-weight:bold; }
+ $title = ''.$title.' '."\n";
+ if ($bibentry->hasField('url')) $title = ''.$title.'';
+
+
+ // author
+ if ($bibentry->hasField('author')) {
+ $coreInfo = $title . ''.$bibentry->getFormattedAuthorsImproved().'';}
+ else $coreInfo = $title;
+
+ // core info usually contains title + author
+ $entry[] = $thumb.$coreInfo;
+
+ // now the book title
+ $booktitle = '';
+ if ($type=="inproceedings") {
+ $booktitle = 'In '.$bibentry->getField(BOOKTITLE); }
+ if ($type=="incollection") {
+ $booktitle = 'Chapter in '.$bibentry->getField(BOOKTITLE);}
+ if ($type=="inbook") {
+ $booktitle = 'Chapter in '.$bibentry->getField('chapter');}
+ if ($type=="article") {
+ $booktitle = 'In '.$bibentry->getField("journal");}
+
+ //// we may add the editor names to the booktitle
+ $editor='';
+ if ($bibentry->hasField(EDITOR)) {
+ $editor = $bibentry->getFormattedEditors();
+ }
+ if ($editor!='') $booktitle .=' ('.$editor.')';
+ // end editor section
+
+ // is the booktitle available
+ if ($booktitle!='') {
+ $entry[] = ' '.$booktitle.'';
+ }
+
+
+ $publisher='';
+ if ($type=="phdthesis") {
+ $publisher = 'PhD thesis, '.$bibentry->getField(SCHOOL);
+ }
+ if ($type=="mastersthesis") {
+ $publisher = 'Master\'s thesis, '.$bibentry->getField(SCHOOL);
+ }
+ if ($type=="bachelorsthesis") {
+ $publisher = 'Bachelor\'s thesis, '.$bibentry->getField(SCHOOL);
+ }
+ if ($type=="techreport") {
+ $publisher = 'Technical report, '.$bibentry->getField("institution");
+ }
+
+ if ($type=="misc") {
+ $publisher = $bibentry->getField('howpublished');
+ }
+
+ if ($bibentry->hasField("publisher")) {
+ $publisher = $bibentry->getField("publisher");
+ }
+
+ if ($publisher!='') $entry[] = ''.$publisher.'';
+
+
+ if ($bibentry->hasField('volume')) $entry[] = "volume ".$bibentry->getField("volume");
+
+
+ if ($bibentry->hasField(YEAR)) $entry[] = $bibentry->getYear();
+
+ $result = implode(", ",$entry).'.';
+
+ // some comments (e.g. acceptance rate)?
+ if ($bibentry->hasField('comment')) {
+ $result .= " (".$bibentry->getField("comment").")";
+ }
+ if ($bibentry->hasField('note')) {
+ $result .= " (".$bibentry->getField("note").")";
+ }
+
+ // add the Coin URL
+ //$result .= "\n".$bibentry->toCoins();
+ $result .= " \n";
+
+ // we add biburl and title to be able to retrieve this important information
+ // using Xpath expressions on the XHTML source
+ $result .= $bibentry->getBibLink();
+ // returns an empty string if no pdf present
+ $result .= $bibentry->getLink('pdf');
+ // returns an empty string if no url present
+ $result .= $bibentry->getLink('url');
+ // returns an empty string if no slides present
+ $result .= $bibentry->getLink('slides');
+ // returns an empty string if no poster present
+ $result .= $bibentry->getLink('poster');
+ // Google Scholar ID. empty string if no gsid present
+ $result .= $bibentry->getGSLink();
+ // returns an empty string if no doi present
+ $result .= $bibentry->getDoiLink();
+
+ $result .= '
';
+
+ return $result;
+} // end style function
+
+/** Class to display a bibliography of a page. */
+class BibliographyDisplay {
+ function setDB(&$bibdatabase) { $this->setEntries($bibdatabase->bibdb); }
+
+ /** sets the entries to be shown */
+ function setEntries(&$entries) { $this->entries = $entries; }
+
+ function setTitle($title) { $this->title = $title; return $this; }
+ function getTitle() { return @$this->title ; }
+
+ /** Displays a set of bibtex entries in an HTML table */
+ function display() {
+ ksort($this->entries); // sort the keys, not the values
+ layoutHeaderHTML();
+ foreach ($this->entries as $ref => $bib) {
+ $bib->setIndex($ref);
+ $bib->toHTML();
+ } // end foreach
+ layoutFooterHTML();
+ } // end function
+} // end class
+
+
+
+?>
+
diff --git a/bibtexbrowser.php b/bibtexbrowser.php
index 45f7513..1d3e6e7 100644
--- a/bibtexbrowser.php
+++ b/bibtexbrowser.php
@@ -1,8 +1,9 @@
+
URL: http://www.monperrus.net/martin/bibtexbrowser/
Feedback & Bug Reports: martin.monperrus@gmail.com
+(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
@@ -16,7 +17,7 @@ License, or (at your option) any later version.
// added on Wednesday, June 01 2011, bug found by Carlos Bras
if (!defined('BIBTEXBROWSER')) {
// this if block ends at the very end of this file, after all class and function declarations.
-define('BIBTEXBROWSER','v20121205');
+define('BIBTEXBROWSER','v20130206');
// *************** CONFIGURATION
@@ -99,10 +100,13 @@ define('BIBTEXBROWSER','v20121205');
@define('Q_ALL', 'all');
@define('Q_ENTRY', 'entry');
@define('Q_KEY', 'key');
+@define('Q_KEYS', 'keys'); // select entries using a JSON array of bibtex keys
+@define('Q_ASSOCKEYS', 'assoc_keys'); // consider Q_KEYS as an associative array, and use the keys of Q_KEYS as item abbrv
@define('Q_SEARCH', 'search');
@define('Q_EXCLUDE', 'exclude');
@define('Q_RESULT', 'result');
@define('Q_ACADEMIC', 'academic');
+@define('Q_BIBLIOGRAPHY', 'bibliography');
@define('Q_DB', 'bibdb');
@define('Q_LATEST', 'latest');
@define('AUTHOR', 'author');
@@ -117,6 +121,10 @@ define('BIBTEXBROWSER','v20121205');
@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'.
+@define('ICONS','[]');
+@define('Q_ICONS','icons');
+
// in embedded mode, we still need a URL for displaying bibtex entries alone
// this is usually resolved to bibtexbrowser.php
// but can be overridden in bibtexbrowser.local.php
@@ -147,6 +155,7 @@ See also zetDB().
function setDB() {
list($db, $parsed, $updated, $saved) = _zetDB(@$_GET[Q_FILE]);
$_GET[Q_DB] = $db;
+ $_GET[Q_ICONS] = (array) json_decode(ICONS);
return $updated;
}
@@ -240,14 +249,14 @@ function _zetDB($bibtex_filenames) {
&& is_readable($compiledbib)
&& filesize($compiledbib)>0
) {
- $f = fopen($compiledbib,'r');
+ $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'); }
+ } else { die("could not get the lock for reading $compiledbib"); }
fclose($f);
// basic test
// do we have an correct version of the file
@@ -299,7 +308,7 @@ function _zetDB($bibtex_filenames) {
fwrite($f,serialize($db));
flock($f,LOCK_UN);
$saved = true;
- } else { die('could not get the lock'); }
+ } else { die("could not get the lock for writing $compiledbib"); }
fclose($f);
} // end saving the cached verions
//else echo '';
@@ -999,12 +1008,73 @@ class BibEntry {
return "http://".$_SERVER['HTTP_HOST'].dirname($_SERVER['SCRIPT_NAME']).'/'.$this->getURL();
}
- /** returns a "[pdf]" link if relevant */
+ /** 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($bibfield,$icon,$def) specifies the icon key $icon and default text $def.
+ */
+ function getLink($bibfield,$icon=NULL,$def=NULL) {
+ if ($icon==NULL) { $icon=$bibfield; }
+ $str = $this->getIconOrTxt($icon,$def);
+ if ($this->hasField($bibfield)) {
+ return ' '.$str.'';
+ }
+ return '';
+ }
+
+ /* a few specializations of getLink */
+
+ /** returns a "[url]" link if relevant. modified to exploit the new method, while keeping backward compatibility */
function getUrlLink() {
- if ($this->hasField('url')) return ' [pdf]';
+ 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')) {
+ return ' '.$str.'';
+ }
return '';
+ }
+
+ /** GS are a special kind of links, where the url depends on the google scholar id */
+ function getGSLink() {
+ $str = $this->getIconOrTxt('gsc','cites');
+ // Google Scholar ID
+ if ($this->hasField('gsid')) {
+ return ' '.$str.'';
+ }
+ return '';
+ }
+
+ /** replace [$ext] with an icon whose url is defined in a string
+ * e.g. getIconOrTxt('pdf') will show the icon defined in $_GET[Q_ICONS]['pdf'] or print '[pdf]'
+ * or getIconOrTxt('pdf','paper') will show the icon defined by $_GET[Q_ICONS]['pdf'] or print '[paper]'
+ * The replacement text is also used if the url does not point to a valid file (using the "alt" property of the "img" html tag)
+ */
+ function getIconOrTxt($ext,$def=NULL) {
+ if ($def==NULL) { $def=$ext; }
+ $icons = $_GET[Q_ICONS];
+ if ( array_key_exists($ext,$icons) ) {
+ $str='';
+ } else {
+ $str='['.$def.']';
+ }
+ return $str;
}
+
+
/** Reruns the abstract */
function getAbstract() {
if ($this->hasField('abstract')) return $this->getField('abstract');
@@ -1182,6 +1252,16 @@ class BibEntry {
return $this->formatAuthor($authors[0]) . $etal;
}
+ /**
+ * Returns a compacted string form of author names by throwing away
+ * all author names except for the first one and appending ", et al."
+ */
+ function getVeryCompactedAuthors(){
+ $authors = $this->getRawAuthors();
+ $etal = count($authors) > 1 ? ', et al.' : '';
+ list($firstname, $lastname) = splitFullName($authors[0]);
+ return $lastname . $etal;
+ }
/** add the link to the homepage if it is defined in a string
* e.g. @string{hp_MartinMonperrus="http://www.monperrus.net/martin"}
@@ -1296,6 +1376,16 @@ class BibEntry {
}
+ /** 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;
+ }
+ }
+
+
/** Outputs an HTML line (
)with two TDS inside
*/
function toTR() {
@@ -1306,27 +1396,23 @@ class BibEntry {
echo $this->getAbbrv().' ';
echo '
';
echo bib2html($this);
+ echo "
\n";
+ }
- $href = 'href="'.$this->getURL().'"';
- if (BIBTEXBROWSER_BIBTEX_LINKS) {
- // we add biburl and title to be able to retrieve this important information
- // using Xpath expressions on the XHTML source
- echo " getKey()."\" {$href}>[bibtex]";
- }
-
- // returns an empty string if no url present
- echo $this->getUrlLink();
+ /** Outputs an LI line (
) with spans for each element, using the value attribute the abbrev. (does not work with x-abbrv) */
+ function toLI() {
+ echo '
';
+ echo '';
+ echo bib2html($this);
+ echo "
\n";
+ }
- if ($this->hasField('doi')) {
- echo ' [doi]';
- }
-
- // Google Scholar ID
- if ($this->hasField('gsid')) {
- echo ' [cites]';
- }
- echo "\n";
+ /** Outputs an DL line (
';
+ break;
+ case 'deflist':
+ echo '';
+ break;
+ }
+}
+
/** this function encapsulates the user-defined name for bib to HTML*/
function bib2html(&$bibentry) {
$function = BIBLIOGRAPHYSTYLE;
@@ -2127,6 +2241,9 @@ else $page = 1;
if (!function_exists('query2title')) {
/** transforms an array representing a query into a formatted string */
function query2title(&$query) {
+ // special case
+ if (isset($query[Q_BIBLIOGRAPHY])) return 'Publications in ' . htmlspecialchars($_SERVER['PHP_SELF']);
+
$headers = array();
foreach($query as $k=>$v) {
if($k == Q_INNER_AUTHOR) { $k = 'author'; }
@@ -2301,21 +2418,87 @@ class SimpleDisplay {
echo 'Options: '.@implode(',',$this->options).' ';
}
- ?>
+ layoutHeaderHTML();
-
- entries);
$i=0;
foreach ($this->entries as $bib) {
// by default, index are in decrasing order
// so that when you add a publicaton recent , the indices of preceding publications don't change
$bib->setIndex('['.($count-($i++)).']');
- $bib->toTR();
+ $bib->toHTML();
} // end foreach
- ?>
-
- ';
+ return ''.$label.'';
+}
+
+
+/**
+ * Displays the summary information of each bib entries of the
+ * current page. For each entry, this method displays the author,
+ * title; the bib entries are displayed grouped by the
+ * publication years. If the bib list is empty, an error message is
+ * displayed.
+ */
+class DefaultContentStrategy {
+
+ /** $display: an instance of PagedDisplay */
+ function display(&$display) {
+ // create a year -> entries map to display by years
+ $years = array();
+ foreach ($display->result as $e) {
+ $y = trim($e->getField(YEAR));
+ $years[$y][$e->getKey()] = $e;
+ }
+ krsort($years);
+
+ layoutHeaderHTML();
+
+ $index = 0;
+ $refnum = count($display->result)-(($display->page-1)*PAGE_SIZE);
+ foreach ($years as $year => $entries) {
+
+ if ($display->isDisplayed($index)) {
+ switch(LAYOUT) {
+ case 'deflist':
+ case 'list':
+ ?>
+
+
+
+
+
+ isDisplayed($index)) {
+ $bib->setAbbrv($refnum--);
+ $bib->toHTML();
+ }
+ $index++;
+
+ } // end foreach
+ }
+ layoutFooterHTML();
+
} // end function
} // end class
@@ -2370,10 +2553,10 @@ class AcademicDisplay {
uasort($entries, ORDER_FUNCTION);
if (count($entries)>0) {
- echo "\n".'
'.$title.'
'."\n";
- echo '
'."\n";
+ echo "\n".'
'.$title.'
'."\n";
+ 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
@@ -2381,11 +2564,11 @@ class AcademicDisplay {
if ($count == NULL) { $count = 1; } // init
$id = $count;
foreach ($entries as $bib) {
- $bib->setIndex('['.($id++).']');
- $bib->toTR();
+ $bib->setIndex($id++);
+ $bib->toHTML();
} // end foreach
$count = @$count + count($entries);
- echo '
';
+ layoutFooterHTML();
}
}
@@ -2397,7 +2580,7 @@ class AcademicDisplay {
foreach (_DefaultBibliographySections() as $section) {
$this->search2html($section['query'],$section['title']);
- }
+ }
}
}
@@ -2827,21 +3010,35 @@ class BibDataBase {
if (count($query)<1) {return array();}
if (isset($query[Q_ALL])) return array_values($this->bibdb);
+ if (array_key_exists( Q_KEYS, $query )) {
+ $keylist = (array) $query[Q_KEYS];
+ $reflist = array_flip($keylist);
+ $is_assoc = array_key_exists( Q_ASSOCKEYS, $query ); //array_values($query[Q_KEYS]) !== $query[Q_KEYS];
+ //if ($is_assoc) echo "Assoc";
+ //print_r($keylist);
+ } else {
+ $is_assoc = false;
+ }
+ unset($query[Q_ASSOCKEYS]); // not used for filtering the bibtex entries
+
$result = array();
foreach ($this->bibdb as $bib) {
$entryisselected = true;
+ $akey = '';
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) {
@@ -2852,20 +3049,36 @@ class BibDataBase {
// 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_KEYS) {
+ if ( ! in_array( $bib->getKey(), $keylist ) ) {
+ //echo $bib->getKey() . " not in list \n";
+ $entryisselected = false;
+ break;
}
+ //echo $bib->getKey() . " in list \n";
}
else {
if (!$bib->hasPhrase($fragment, $field)) {
$entryisselected = false;
+ break;
}
}
}
if ($entryisselected) {
- $result[] = $bib;
+ if ( $is_assoc ) {
+ $result[$reflist[$bib->getKey()]] = $bib;
+ } else {
+ $result[] = $bib;
+ }
+ } else {
+ //echo "entry ".$bib->getKey()." not selected\n";
}
}
-
+ //foreach ($result as $ref=>$bib) {echo $ref." => ".$bib->getKey()." ";}
return $result;
}
} // end class
@@ -3018,7 +3231,7 @@ echo '
-
+
getRSS()!='') echo '';
?>
@@ -3176,18 +3389,18 @@ class PagedDisplay {
}
$this->menu($less, $more);
- echo '
';
@@ -3478,7 +3691,7 @@ class Dispatcher {
function keywords() { $this->query[Q_TAG]=$_GET[Q_TAG]; }
- function author() {
+ function author() {
// Friday, October 29 2010
// changed from 'author' to '_author'
// in order to search at the same time "Joe Dupont" an "Dupont, Joe"
@@ -3535,11 +3748,30 @@ class Dispatcher {
else { nonExistentBibEntryError(); }
}
+ function bibliography() {
+ $this->displayer='BibliographyDisplay';
+ $this->query[Q_ASSOCKEYS]=1;
+ }
+
+ function layout() { $this->query[LAYOUT]=$_GET[LAYOUT]; }
+
+ function keys() {
+ if (preg_match('/utf-?8/i',ENCODING)) {
+ // Create array from list of bibtex entries
+ $_GET[Q_KEYS] = json_decode($_GET[Q_KEYS]);
+ }
+ $this->query[Q_KEYS]=$_GET[Q_KEYS];
+ }
+
+ function assoc_keys() {
+ $this->query[Q_ASSOCKEYS]=$_GET[Q_ASSOCKEYS];
+ }
+
/** is used to remotely analyzed a situation */
function diagnosis() {
header('Content-type: text/plain');
echo "php version: ".phpversion()."\n";
- echo "bibtexbrowser version: 20121205\n";
+ echo "bibtexbrowser version: 20130226\n";
echo "dir: ".decoct(fileperms(dirname(__FILE__)))."\n";
echo "bibtex file: ".decoct(fileperms($_GET[Q_FILE]))."\n";
exit;
@@ -3551,7 +3783,7 @@ class Dispatcher {
-
+
You are browsing with bibtexbrowser
@@ -3573,4 +3805,4 @@ class Dispatcher {
$class = BIBTEXBROWSER_MAIN;// extension point
$main = new $class();
$main->main();
-?>
\ No newline at end of file
+?>