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 modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. */ // it is be possible to include( 'bibtexbrowser.php' ); several times in the same script // added on Wednesday, June 01 2011, bug found by Carlos Bras if (!defined('BIBTEXBROWSER')) { // this if block ends at the very end of this file, after all class and function declarations. define('BIBTEXBROWSER','v20121205'); // *************** CONFIGURATION // I recommend to put your changes in bibtexbrowser.local.php // it will help you to upgrade the script with a new version // the changes that require existing bibtexbrowser symbols should be in bibtexbrowser.after.php (included at the end of this file) @include(preg_replace('/\.php$/','.local.php',__FILE__)); // there is no encoding transformation from the bibtex file to the html file // if your bibtex file contains 8 bits characters in utf-8 // change the following parameter @define('ENCODING','UTF-8');//@define('ENCODING','iso-8859-1');//define('ENCODING','windows-1252'); // number of bib items per page // we use the same parameter 'num' as Google @define('PAGE_SIZE',isset($_GET['num'])?(preg_match('/^\d+$/',$_GET['num'])?$_GET['num']:10000):14); // 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 // @define('BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT',false); @define('BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT',true); // if you disable the Javascript progressive enhancement, // you may want the links to be open in a new window/tab // if yes, add in bibtexbrowser.local.php define('BIBTEXBROWSER_BIB_IN_NEW_WINDOW',true); @define('BIBTEXBROWSER_BIB_IN_NEW_WINDOW',false); @define('BIBLIOGRAPHYSTYLE','DefaultBibliographyStyle');// this is the name of a function @define('BIBLIOGRAPHYSECTIONS','DefaultBibliographySections');// this is the name of a function // can we load bibtex files on external servers? @define('BIBTEXBROWSER_LOCAL_BIB_ONLY', true); // the default view in {SimpleDisplay,AcademicDisplay,RSSDisplay,BibtexDisplay} @define('BIBTEXBROWSER_DEFAULT_DISPLAY','SimpleDisplay'); // the target frame of menu links @define('BIBTEXBROWSER_MENU_TARGET','main'); // might be define('BIBTEXBROWSER_MENU_TARGET','_self'); in bibtexbrowser.local.php @define('ABBRV_TYPE','index');// may be year/x-abbrv/key/none/index // Wrapper to use when we are included by another script @define('BIBTEXBROWSER_EMBEDDED_WRAPPER', 'NoWrapper'); // Wrapper to use when we are included by another script @define('BIBTEXBROWSER_MAIN', 'Dispatcher'); // default order functions @define('ORDER_FUNCTION','compare_bib_entry_by_year_and_month'); // can be @define('ORDER_FUNCTION','compare_bib_entry_by_title'); // only displaying the n newest entries @define('BIBTEXBROWSER_NEWEST',5); @define('BIBTEXBROWSER_NO_DEFAULT', false); // do we add [bibtex] links ? // suggested by Sascha Schnepp @define('BIBTEXBROWSER_BIBTEX_LINKS',true); // should authors be linked to [none/homepage/resultpage] // none: nothing // their homepage if defined as @strings // their publication lists according to this bibtex @define('BIBTEXBROWSER_AUTHOR_LINKS','homepage'); @define('BIBTEXBROWSER_DEBUG',false); @define('COMMA_NAMES',false);// do have authors in a comma separated form? @define('TYPES_SIZE',10); // number of entry types per table @define('YEAR_SIZE',20); // number of years per table @define('AUTHORS_SIZE',30); // number of authors per table @define('TAGS_SIZE',30); // number of keywords per table @define('READLINE_LIMIT',1024); @define('Q_YEAR', 'year'); @define('Q_YEAR_PAGE', 'year_page'); @define('Q_FILE', 'bib'); @define('Q_AUTHOR', 'author'); @define('Q_AUTHOR_PAGE', 'author_page'); @define('Q_TAG', 'keywords'); @define('Q_TAG_PAGE', 'keywords_page'); @define('Q_TYPE', 'type');// used for queries @define('Q_TYPE_PAGE', 'type_page'); @define('Q_ALL', 'all'); @define('Q_ENTRY', 'entry'); @define('Q_KEY', 'key'); @define('Q_SEARCH', 'search'); @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'); @define('TITLE', 'title'); @define('BOOKTITLE', 'booktitle'); @define('YEAR', 'year'); @define('BUFFERSIZE',100000); @define('MULTIPLE_BIB_SEPARATOR',';'); @define('METADATA_GS',true); @define('METADATA_DC',true); @define('METADATA_EPRINTS',false); @define('LAYOUT','table'); // may be table/list/deflist. defines the HTML rendering options (,
    /
'; echo ' '; echo '\n"; // toTR() must be self-contained } /** Outputs an LI line with SPANs for each element, setting the item value according to getAbbrv(). */ function toLI() { echo '
  • '; $this->anchor(); echo bib2html($this); echo "
  • \n"; } /** Outputs an DL line (
    +
    ) */ function toDD() { echo '
    '; $this->anchor(); echo $this->getAbbrv().'
    '; echo bib2html($this); echo "
    \n"; } /** Outputs an coins URL: see http://ocoins.info/cobg.html * Used by Zotero, mendeley, etc. */ function toCoins() { $url_parts=array(); $url_parts[]='ctx_ver=Z39.88-2004'; $type = $this->getType(); if ($type=="book") { $url_parts[]='rft_val_fmt='.s3988('info:ofi/fmt:kev:mtx:book'); $url_parts[]='rft.btitle='.s3988($this->getTitle()); $url_parts[]='rft.genre=book'; } else if ($type=="inproceedings") { $url_parts[]='rft_val_fmt='.s3988('info:ofi/fmt:kev:mtx:book'); $url_parts[]='rft.atitle='.s3988($this->getTitle()); $url_parts[]='rft.btitle='.s3988($this->getField(BOOKTITLE)); // zotero does not support with this proceeding and conference // they give the wrong title //$url_parts[]='rft.genre=proceeding'; //$url_parts[]='rft.genre=conference'; $url_parts[]='rft.genre=bookitem'; } else if ($type=="incollection" ) { $url_parts[]='rft_val_fmt='.s3988('info:ofi/fmt:kev:mtx:book'); $url_parts[]='rft.btitle='.s3988($this->getField(BOOKTITLE)); $url_parts[]='rft.atitle='.s3988($this->getTitle()); $url_parts[]='rft.genre=bookitem'; } else if ($type=="article") { $url_parts[]='rft_val_fmt='.s3988('info:ofi/fmt:kev:mtx:journal'); $url_parts[]='rft.atitle='.s3988($this->getTitle()); $url_parts[]='rft.jtitle='.s3988($this->getField("journal")); $url_parts[]='rft.volume='.s3988($this->getField("volume")); $url_parts[]='rft.issue='.s3988($this->getField("issue")); } else { // techreport, phdthesis $url_parts[]='rft_val_fmt='.s3988('info:ofi/fmt:kev:mtx:book'); $url_parts[]='rft.btitle='.s3988($this->getTitle()); $url_parts[]='rft.genre=report'; } $url_parts[]='rft.pub='.s3988($this->getPublisher()); // referent if ($this->hasField('url')) { $url_parts[]='rft_id='.s3988($this->getField("url")); } else if ($this->hasField('doi')) { $url_parts[]='rft_id='.s3988('info:doi/'.$this->getField("doi")); } // 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]); $url_parts[]='rft.date='.s3988($this->getYear()); foreach ($this->getFormattedAuthors() as $au) $url_parts[]='rft.au='.s3988($au); return ''; } /** * rebuild the set of constants used if any as a string */ function getConstants() { $result=''; foreach ($this->constants as $k=>$v) { $result.='@string{'.$k.'="'.$v."\"}\n"; } return $result; } /** * Displays a
     text of the given bib entry.
       * URLs are replaced by HTML links.
       */
      function toEntryUnformatted() {
        $result = "";
        $result .= '
    '; // pre is nice when it is embedded with no CSS available
        $entry = str_replace('<','<',$this->getFullText());
        if ($this->hasField('url')) {
          $url = $this->getField('url');
          // this is not a parsing but a simple replacement
          $entry = str_replace($url,''.$url.'', $entry);
        }
    
        $result .=  $entry;
        $result .=  '
    '; return $result; } /** * Gets the raw text of the entry (crossref + strings + entry) */ function getFullText() { $s = ''; // adding the crossref if necessary if ($this->crossref!=null) { $s .= $this->crossref->getFullText()."\n";} $s.=$this->getConstants(); $s.=$this->getText(); return $s; } } function layoutHeaderHTML() { $tag = ''; switch(LAYOUT) { /* switch for different layouts */ case 'list': if (ABBRV_TYPE=='index') { $tag='ol'; } else { // assume none $tag='ul'; } break; case 'table': $tag = 'table'; break; case 'deflist': $tag = 'div'; break; default: die('Unknown LAYOUT'); } echo '<' . $tag . ' class="result">'; return $tag; } function layoutFooterHTML($tag) { echo ''; } /** this function encapsulates the user-defined name for bib to HTML*/ function bib2html(&$bibentry) { $function = BIBLIOGRAPHYSTYLE; $str = $function($bibentry); $href = 'href="'.$bibentry->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 $str .= " getKey()."\" {$href}>[bibtex]"; } // returns an empty string if no url present $str .= $bibentry->getUrlLink(); if ($bibentry->hasField('doi')) { $str .= ' [doi]'; } // Google Scholar ID if ($bibentry->hasField('gsid')) { $str .= ' [cites]'; } return $str; } /** 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 * @author Jan Geldmacher */ function compare_bib_entry_by_month($a, $b) { // this was the old behavior // return strcmp($a->getKey(),$b->getKey()); //bibkey which is used for sorting $sort_key = 'month'; //desired order of values $sort_order_values = array('jan','january','feb','february','mar','march','apr','april','may','jun','june','jul','july','aug','august','sep','september','oct','october','nov','november','dec','december'); //order: 1=as specified in $sort_order_values or -1=reversed $order = -1; //first check if the search key exists if (!array_key_exists($sort_key,$a->fields) && !array_key_exists($sort_key,$b->fields)) { //neither a nor b have the key -> we compare the keys $retval=strcmp($a->getKey(),$b->getKey()); } elseif (!array_key_exists($sort_key,$a->fields)) { //only b has the field -> b is greater $retval=-1; } elseif (!array_key_exists($sort_key,$b->fields)) { //only a has the key -> a is greater $retval=1; } else { //both have the key, sort using the order given in $sort_order_values $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)) { //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)) { //a is not in the search array or a b is greater $retval=-1; } elseif (($val_b === FALSE) || (($val_a > $val_b))){ //b is not in the search array or a>b -> a is greater $retval=1; } } return $order*$retval; } /** is the default sectioning for AcademicDisplay (books, articles, proceedings, etc. ) */ function DefaultBibliographySections() { return array( // Books array( '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'), 'title' => 'Refereed Articles' ), // conference papers array( 'query' => array(Q_TYPE=>'inproceedings|conference',Q_EXCLUDE=>'workshop'), 'title' => 'Refereed Conference Papers' ), // workshop papers array( 'query' => array(Q_TYPE=>'inproceedings',Q_SEARCH=>'workshop'), 'title' => 'Refereed Workshop Papers' ), // misc and thesis array( 'query' => array(Q_TYPE=>'misc|phdthesis|mastersthesis|bachelorsthesis|techreport'), 'title' => 'Other Publications' ) ); } /** transforms a $bibentry into an HTML string. It is called by function bib2html if the user did not choose a specific style the default usable CSS styles are .bibtitle { font-weight:bold; } .bibbooktitle { font-style:italic; } .bibauthor { } .bibpublisher { } */ function DefaultBibliographyStyle(&$bibentry) { $title = $bibentry->getTitle(); $type = $bibentry->getType(); // later on, all values of $entry will be joined by a comma $entry=array(); // title // usually in bold: .bibtitle { font-weight:bold; } $title = ''.$title.''; 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[] = $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(); return $result; } /** is the Bibtexbrowser style contributed by Janos Tapolcai. It looks like the IEEE transaction style. usage: Add the following line in "bibtexbrowser.local.php"
    define('BIBLIOGRAPHYSTYLE','JanosBibliographyStyle');
    
    */ function JanosBibliographyStyle(&$bibentry) { $title = $bibentry->getTitle(); $type = $bibentry->getType(); $entry=array(); // author if ($bibentry->hasField('author')) { $entry[] = $bibentry->formattedAuthors(); } // title $title = '"'.$title.'"'; if ($bibentry->hasField('url')) $title = ' '.$title.''; $entry[] = $title; // now the origin of the publication is in italic $booktitle = ''; if (($type=="misc") && $bibentry->hasField("note")) { $booktitle = $bibentry->getField("note"); } if ($type=="inproceedings") { $booktitle = 'In '.$bibentry->getField(BOOKTITLE); } if ($type=="incollection") { $booktitle = 'Chapter in '.$bibentry->getField(BOOKTITLE); } if ($type=="article") { $booktitle = 'In '.$bibentry->getField("journal"); } //// ******* EDITOR $editor=''; if ($bibentry->hasField(EDITOR)) { $editor = $bibentry->getFormattedEditors(); } if ($booktitle!='') { if ($editor!='') $booktitle .=' ('.$editor.')'; $entry[] = ''.$booktitle.''; } $publisher=''; if ($type=="phdthesis") { $publisher = 'PhD thesis, '.$bibentry->getField(SCHOOL); } if ($type=="mastersthesis") { $publisher = 'Master\'s thesis, '.$bibentry->getField(SCHOOL); } if ($type=="techreport") { $publisher = 'Technical report, '.$bibentry->getField("institution"); } if ($bibentry->hasField("publisher")) { $publisher = $bibentry->getField("publisher"); } if ($publisher!='') $entry[] = $publisher; if ($bibentry->hasField('volume')) $entry[] = "vol. ".$bibentry->getField("volume"); if ($bibentry->hasField('number')) $entry[] = 'no. '.$bibentry->getField("number"); if ($bibentry->hasField('address')) $entry[] = $bibentry->getField("address"); if ($bibentry->hasField('pages')) $entry[] = str_replace("--", "-", "pp. ".$bibentry->getField("pages")); if ($bibentry->hasField(YEAR)) $entry[] = $bibentry->getYear(); $result = implode(", ",$entry).'.'; // some comments (e.g. acceptance rate)? if ($bibentry->hasField('comment')) { $result .= " (".$bibentry->getField("comment").")"; } // add the Coin URL $result .= "\n".$bibentry->toCoins(); return $result; } // ---------------------------------------------------------------------- // DISPLAY MANAGEMENT // ---------------------------------------------------------------------- /** 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) { 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) { // 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); } /** 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 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); // the author format is "Joe Dupont" if (strpos($author,',')===false) { $parts=explode(' ', $author); // get the last name $lastname = array_pop($parts); $firstname = implode(" ", $parts); } // the author format is "Dupont, J." else { $parts=explode(',', $author); // get the last name $lastname = str_replace(',','',array_shift($parts)); $firstname = implode(" ", $parts); } return array(trim($firstname), trim($lastname)); } /** 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() { if (!isset($_GET[Q_DB])) {die('Did you forget to call setDB() before instantiating this class?');} $yearIndex = $_GET[Q_DB]->yearIndex(); echo '
    Year: '; $formatedYearIndex = array(); $formatedYearIndex[] = ''.*')).'>All'; foreach($yearIndex as $year) { $formatedYearIndex[] = '$year)).'>'.$year.''; } // by default the separator is a | echo implode('|',$formatedYearIndex); echo '
    '; } } /** Returns the powered by part. @nodoc */ 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 ?> $db = zetDB('metrics.bib'); $menu = new MenuManager(); $menu->setDB($db); $menu->year_size=100;// should display all years :) $menu->display();
    */ class MenuManager { /** The bibliographic database, an instance of class BibDataBase. */ var $db; var $type_size = TYPES_SIZE; var $year_size = YEAR_SIZE; var $author_size = AUTHORS_SIZE; var $tag_size = TAGS_SIZE; function MenuManager() { } /** sets the database that is used to create the menu */ function setDB(&$db) { $this->db =$db; return $this; } function getTitle() { return ''; } /** function called back by HTMLWrapper */ function display() { echo $this->searchView().'
    '; echo $this->typeVC().'
    '; echo $this->yearVC().'
    '; echo $this->authorVC().'
    '; echo $this->tagVC().'
    '; } /** Displays the title in a table. */ function titleView() { ?>
    '; $this->anchor(); echo $this->getAbbrv().''; echo bib2html($this); echo "
    Generated from

    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, $this->type_size, Q_TYPE_PAGE, Q_INNER_TYPE); } /** Displays and controls the authors menu in a table. */ function authorVC() { // retrieve authors list to display $authors = $this->db->authorIndex(); // determine the authors page to display if (isset($_GET[Q_AUTHOR_PAGE])) { $page = $_GET[Q_AUTHOR_PAGE]; } else $page = 1; $this->displayMenu('Authors', $authors, $page, $this->author_size, Q_AUTHOR_PAGE, Q_AUTHOR); } /** Displays and controls the tag menu in a table. */ function tagVC() { // retrieve authors list to display $tags = $this->db->tagIndex(); // determine the authors page to display if (isset($_GET[Q_TAG_PAGE])) { $page = $_GET[Q_TAG_PAGE]; } else $page = 1; if (count($tags)>0) $this->displayMenu('Keywords', $tags, $page, $this->tag_size, Q_TAG_PAGE, Q_TAG); } /** Displays and controls the tag menu in a table. */ function yearVC() { // retrieve authors list to display $years = $this->db->yearIndex(); // determine the authors page to display if (isset($_GET[Q_YEAR_PAGE])) { $page = $_GET[Q_YEAR_PAGE]; } else $page = 1; $this->displayMenu('Years', $years, $page, $this->year_size, Q_YEAR_PAGE, Q_YEAR); } /** Displays the main contents . */ function mainVC() { $this->display->display(); } /** Displays a list menu in a table. * * $title: title of the menu (string) * $list: list of menu items (string) * $page: page number to display (number) * $pageSize: size of each page * $pageKey: URL query name to send the page number to the server * $targetKey: URL query name to send the target of the menu item */ function displayMenu($title, $list, $page, $pageSize, $pageKey, $targetKey) { $numEntries = count($list); $startIndex = ($page - 1) * $pageSize; $endIndex = $startIndex + $pageSize; ?> 0) { $href = makeHref(array($queryKey => $page - 1,'menu'=>''));//menuPageBar $result .= '[prev]\n"; } // (1 page) forward (>) if ($end < $numEntries) { $href = makeHref(array($queryKey => $page + 1,'menu'=>''));//menuPageBar $result .= '[next]\n"; } return $result; } /** * Displays menu items (anchors) from the start index (inclusive) to * the end index (exclusive). For each menu, the following form of * string is printed: * * * Cheon, Yoonsik *
    */ function displayMenuItems($items, $startIndex, $endIndex, $queryKey) { $index = 0; foreach ($items as $key => $item) { if ($index >= $startIndex && $index < $endIndex) { $href = makeHref(array($queryKey => $key)); echo ''. $item ."\n"; echo "
    \n"; } $index++; } } } if (!function_exists('query2title')) { /** transforms an array representing a query into a formatted string */ function query2title(&$query) { $headers = array(); foreach($query as $k=>$v) { if($k == 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 '.htmlspecialchars($_GET[Q_FILE]); if (isset($headers[Q_AUTHOR])) $headers[Q_AUTHOR] = 'Publications of '.htmlspecialchars($_GET[Q_AUTHOR]); return join(' & ',$headers); } } /** displays the latest modified bibtex entries. usage:
      $db = zetDB('metrics.bib');
      $d = new NewEntriesDisplay();
      $d->setDB($db);
      $d->setN(7);// optional 
      $d->display();
    
    */ class NewEntriesDisplay { var $n=5; var $db; function setDB(&$bibdatabase) { $this->db = $bibdatabase; } function setN($n) {$this->n = $n;return $this;} /** sets the entries to be shown */ function setEntries(&$entries) { $this->db = createBibDataBase(); $this->db->bibdb = $entries; } /** 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(); } } /** 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; function setDB(&$bibdatabase) { $this->setEntries($bibdatabase->bibdb); } /** creates a YearDisplay */ function setOptions(&$options) {} 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); } } } /** 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); } /** 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); } function indexDown() { $index=count($this->entries); foreach ($this->entries as $bib) { $bib->setAbbrv((string)$index--); } // end foreach return $this->entries; } function setTitle($title) { $this->title = $title; return $this; } function getTitle() { return @$this->title ; } /** Displays a set of bibtex entries in an HTML table */ function display() { uasort($this->entries, ORDER_FUNCTION); if ($this->options) { foreach($this->options as $fname=>$opt) { $this->$fname($opt,$entries); } } if (BIBTEXBROWSER_DEBUG) { echo 'Style: '.BIBLIOGRAPHYSTYLE.'
    '; echo 'Order: '.ORDER_FUNCTION.'
    '; echo 'Abbrv: '.ABBRV_TYPE.'
    '; echo 'Options: '.@implode(',',$this->options).'
    '; } $tag = layoutHeaderHTML(); $count = count($this->entries); $i=0; foreach ($this->entries as $bib) { // by default, index are in decreasing order // so that when you add a publicaton recent , the indices of preceding publications don't change $bib->setIndex($count-($i++)); $bib->toHTML(); } // end foreach layoutFooterHTML($tag); } // end function } // end class /** returns an HTTP 404 and displays en error message. */ function nonExistentBibEntryError() { header('HTTP/1.1 404 Not found'); ?> 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 { function getTitle() { return $this->title; } function setTitle($title) { $this->title = $title; return $this; } function setDB(&$bibdatabase) { $this->setEntries($bibdatabase->bibdb); } /** sets the entries to be shown */ function setEntries(&$entries) { $this->entries = $entries; } /** transforms a query to HTML * $ 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"; $tag = layoutHeaderHTML(); // 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->setIndex($id++); $bib->toHTML(); } // end foreach $count = @$count + count($entries); layoutFooterHTML($tag); } } function display() { $this->db = createBibDataBase(); $this->db->bibdb = $this->entries; foreach (_DefaultBibliographySections() as $section) { $this->search2html($section['query'],$section['title']); } } } /** 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; 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().'
    '; $abstract = ''; if ($this->bib->hasField('abstract')) { $abstract = '
    Abstract:
    '.$this->bib->getAbstract().'
    '; } $download = ''; if ($this->bib->hasField('url')) { $download = ''; } $reference= '
    Reference:
    '.strip_tags(bib2html($this->bib)).'
    '; $bibtex = '
    Bibtex Entry:
    '.$this->bib->toEntryUnformatted().''; return $subtitle.$abstract.$download.$reference.$bibtex.$this->bib->toCoins(); } function display() { // we encapsulate everything so that the output of display() is still valid XHTML echo '
    '; //echo $this->display_old(); echo $this->displayOnSteroids(); echo '
    '; } // old display function display_old() { return $this->bib->toCoins().$this->bib->toEntryUnformatted(); } /** Creates metadata for Google Scholar * + a description * @see http://scholar.google.com/intl/en/scholar/inclusion.html * @see http://www.monperrus.net/martin/accurate+bibliographic+metadata+and+google+scholar * */ function metadata() { $result=array(); if (METADATA_GS) { // the description may mix with the Google Scholar tags // we remove it // $result[] = array('description',trim(strip_tags(str_replace('"','',bib2html($this->bib))))); $result[] = array('citation_title',$this->bib->getTitle()); $authors = $this->bib->getArrayOfCommaSeparatedAuthors(); $result[] = array('citation_authors',implode("; ",$authors)); foreach($authors as $author) { $result[] = array('citation_author',$author); } $result[] = array('citation_publication_date',$this->bib->getYear()); // this page $result[] = array('citation_abstract_html_url','http://'.$_SERVER['HTTP_HOST'].($_SERVER['SERVER_PORT']=='80'?'':$_SERVER['SERVER_PORT']).str_replace('&','&',$_SERVER['REQUEST_URI'])); if ($this->bib->hasField("publisher")) { $result[] = array('citation_publisher',$this->bib->getPublisher()); } // BOOKTITLE: JOURNAL NAME OR PROCEEDINGS if ($this->bib->getType()=="article") { // journal article $result[] = array('citation_journal_title',$this->bib->getField("journal")); $result[] = array('citation_volume',$this->bib->getField("volume")); if ($this->bib->hasField("issue")) { $result[] = array('citation_issue',$this->bib->getField("issue")); } if ($this->bib->hasField("issn")) { $result[] = array('citation_issue',$this->bib->getField("issn")); } } if ($this->bib->getType()=="inproceedings" || $this->bib->getType()=="conference") { $result[] = array('citation_conference_title',$this->bib->getField(BOOKTITLE)); $result[] = array('citation_conference',$this->bib->getField(BOOKTITLE)); } if ($this->bib->getType()=="phdthesis" || $this->bib->getType()=="mastersthesis" || $this->bib->getType()=="bachelorsthesis" ) { $result[] = array('citation_dissertation_institution',$this->bib->getField('school')); } if ($this->bib->getType()=="techreport" && $this->bib->hasField("number") ) { $result[] = array('citation_technical_report_number',$this->bib->getField('number')); } if ($this->bib->getType()=="techreport" && $this->bib->hasField("institution") ) { $result[] = array('citation_technical_report_institution',$this->bib->getField('institution')); } // generic if ($this->bib->hasField("doi")) { $result[] = array('citation_doi',$this->bib->getField("doi")); } if ($this->bib->hasField("url")) { $result[] = array('citation_pdf_url',$this->bib->getField("url")); } } // we don't introduce yet another kind of bibliographic metadata // the core bibtex metadata will simply be available as json // now adding the pure bibtex with no translation //foreach ($this->bib->getFields() as $k => $v) { // if (!preg_match("/^_/",$k)) { // $result[] = array("bibtex:".$k,$v); // } //} // a fallback to essential dublin core // Dublin Core should not be used for bibliographic metadata // according to several sources // * Google Scholar: "Use Dublin Core tags (e.g., DC.title) as a last resort - they work poorly for journal papers" // * http://reprog.wordpress.com/2010/09/03/bibliographic-data-part-2-dublin-cores-dirty-little-secret/ // however it seems that Google Scholar needs at least DC.Title to trigger referencing // reference documentation: http://dublincore.org/documents/dc-citation-guidelines/ if (METADATA_DC) { $result[] = array('DC.Title',$this->bib->getTitle()); foreach($this->bib->getArrayOfCommaSeparatedAuthors() as $author) { $result[] = array('DC.Creator',$author); } $result[] = array('DC.Issued',$this->bib->getYear()); } // --------------------------------- BEGIN METADATA EPRINTS // and now adding eprints metadata // why adding eprints metadata? // because eprints is a well known bibliographic software and several crawlers/desktop software // use their metadata // unfortunately, the metadata is even less documented than Google Scholar citation_ // reference documentation: the eprints source code (./perl_lib/EPrints/Plugin/Export/Simple.pm) // examples: conference paper: http://tubiblio.ulb.tu-darmstadt.de/44344/ // journal paper: http://tubiblio.ulb.tu-darmstadt.de/44344/ if (METADATA_EPRINTS) { $result[] = array('eprints.title',$this->bib->getTitle()); $authors = $this->bib->getArrayOfCommaSeparatedAuthors(); foreach($authors as $author) { $result[] = array('eprints.creators_name',$author); } $result[] = array('eprints.date',$this->bib->getYear()); if ($this->bib->hasField("publisher")) { $result[] = array('eprints.publisher',$this->bib->getPublisher()); } if ($this->bib->getType()=="article") { // journal article $result[] = array('eprints.type','article'); $result[] = array('eprints.publication',$this->bib->getField("journal")); $result[] = array('eprints.volume',$this->bib->getField("volume")); if ($this->bib->hasField("issue")) { $result[] = array('eprints.number',$this->bib->getField("issue"));} } if ($this->bib->getType()=="inproceedings" || $this->bib->getType()=="conference") { $result[] = array('eprints.type','proceeding'); $result[] = array('eprints.book_title',$this->bib->getField(BOOKTITLE)); } if ($this->bib->getType()=="phdthesis" || $this->bib->getType()=="mastersthesis" || $this->bib->getType()=="bachelorsthesis" ) { $result[] = array('eprints.type','thesis'); $result[] = array('eprints.institution',$this->bib->getField('school')); } if ($this->bib->getType()=="techreport") { $result[] = array('eprints.type','monograph'); if ($this->bib->hasField("number")) { $result[] = array('eprints.number',$this->bib->getField('number')); } if ($this->bib->hasField("institution")) { $result[] = array('eprints.institution',$this->bib->getField('institution')); } } // generic if ($this->bib->hasField("doi")) { $result[] = array('eprints.id_number',$this->bib->getField("doi")); } if ($this->bib->hasField("url")) { $result[] = array('eprints.official_url',$this->bib->getField("url")); } } // --------------------------------- END METADATA EPRINTS return $result; } } // ---------------------------------------------------------------------- // DATABASE MANAGEMENT // ---------------------------------------------------------------------- /** represents a bibliographic database that contains a set of bibliographic entries. usage:
    $db = new BibDataBase();
    $db->load('metrics.bib');
    $query = array('author'=>'martin', 'year'=>2008);
    foreach ($db->multisearch($query) as $bibentry) { echo $bibentry->getTitle(); }
    
    */ class BibDataBase { /** A hash table from keys (e.g. Goody1994) to bib entries (BibEntry instances). */ var $bibdb; /** A hashtable of constant strings */ var $stringdb; /** Creates a new database by parsing bib entries from the given * file. (backward compatibility) */ function load($filename) { $this->update($filename); } /** Updates a database (replaces the new bibtex entries by the most recent ones) */ function update($filename) { $empty_array = array(); $db = createBibDBBuilder(); $db->setData($empty_array, $this->stringdb); $db->build($filename); $this->stringdb = array_merge($this->stringdb, $db->stringdb); $result = $db->builtdb; foreach ($result as $b) { // new entries: if (!isset($this->bibdb[$b->getKey()])) { //echo 'adding...
    '; $this->bibdb[$b->getKey()] = $b; } // update entry else if (isset($this->bibdb[$b->getKey()]) && ($b->getText() !== $this->bibdb[$b->getKey()]->getText())) { //echo 'replacing...
    '; $this->bibdb[$b->getKey()] = $b; } } // some entries have been removed foreach ($this->bibdb as $e) { if (!isset($result[$e->getKey()]) && $e->filename==$filename // bug reported by Thomas on Dec 4 2012 ) { //echo 'deleting...
    '; unset($this->bibdb[$e->getKey()]); } } } /** Creates a new empty database */ function BibDataBase() { $this->bibdb = array(); $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() { return $this->bibdb; } /** tests wheter the database contains a bib entry with $key */ function contains($key) { return isset($this->bibdb[$key]); } /** Returns all entries categorized by types. The returned value is * a hashtable from types to arrays of bib entries. */ function getEntriesByTypes() { $result = array(); foreach ($this->bibdb as $b) { $result[$b->getType()][] = $b; } return $result; } /** Returns an array containing all the bib types (strings). */ function getTypes() { $result = array(); foreach ($this->bibdb as $b) { $result[$b->getType()] = 1; } $result = array_keys($result); return $result; } /** Generates and returns an array consisting of all authors. * The returned array is a hash table with keys * and values . */ function authorIndex(){ $result = array(); foreach ($this->bibdb as $bib) { foreach($bib->getRawAuthors() as $a){ //we use an array because several authors can have the same lastname @$result[$bib->getLastName($a)][$bib->formatAuthor($a)]++; } } ksort($result); // now authors are sorted by last name // we rebuild a new array for having good keys in author page $realresult = array(); foreach($result as $x) { ksort($x); foreach($x as $v => $tmp) $realresult[$v] = $v; } return $realresult; } /** Generates and returns an array consisting of all tags. */ function tagIndex(){ $result = array(); foreach ($this->bibdb as $bib) { if (!$bib->hasField("keywords")) continue; $tags =preg_split('/[,;\\/]/', $bib->getField("keywords")); foreach($tags as $a){ $ta = trim($a); $result[$ta] = $ta; } } asort($result); return $result; } /** Generates and returns an array consisting of all years. */ function yearIndex(){ $result = array(); foreach ($this->bibdb as $bib) { if (!$bib->hasField("year")) continue; $year = $bib->getField("year"); $result[$year] = $year; } arsort($result); return $result; } /** Given its key, return the bib entry. */ function getEntryByKey($key) { return $this->bibdb[$key]; } /** * Returns an array containing all bib entries matching the given * type. */ function searchType($type){ $result = array(); foreach($this->bibdb as $bib) { if($bib->getType() == $type) $result[] = $bib; } return $result; } /** 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 */ function multisearch($query) { if (count($query)<1) {return array();} if (isset($query[Q_ALL])) return array_values($this->bibdb); $result = array(); foreach ($this->bibdb as $bib) { $entryisselected = true; foreach ($query as $field => $fragment) { $field = strtolower($field); if ($field==Q_SEARCH) { // we search in the whole bib entry if (!$bib->hasPhrase($fragment)) { $entryisselected = false; } } else if ($field==Q_EXCLUDE) { if ($bib->hasPhrase($fragment)) { $entryisselected = false; } } else if ($field==Q_TYPE || $field==Q_INNER_TYPE) { // types are always exact search // remarks Ken // type:"book" should only select book (and not inbook, book, bookchapter) // this was before in Dispatch:type() // moved here so that it is also used by AcademicDisplay:search2html() if (!$bib->hasPhrase('^('.$fragment.')$', Q_INNER_TYPE)) { $entryisselected = false; } } else { if (!$bib->hasPhrase($fragment, $field)) { $entryisselected = false; } } } if ($entryisselected) { $result[] = $bib; } } return $result; } } // end class /** returns the default CSS of bibtexbrowser */ function bibtexbrowserDefaultCSS() { ?> /* title */ .bibtitle { font-weight:bold; } /* author */ .bibauthor { /* nothing by default */ } /* booktitle (e.g. proceedings title, journal name, etc )*/ .bibbooktitle { font-style:italic; } /* publisher */ .bibpublisher { /* nothing by default */ } .title { color: #003366; font-size: large; font-weight: bold; text-align: right; } .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; } .rheader { font-weight: bold; background-color: #003366; color: #ffffff; padding: 2px; margin-bottom: 10px; border-bottom: #ff6633 2px solid; } .menu { font-size: x-small; background-color: #EFDDB4; padding: 0px; border: 1px solid #000000; margin: 0px; } .menu a { text-decoration: none; color: #003366; } .menu a:hover { color: #ff6633; } .bibref { padding:7px; padding-left:15px; vertical-align:text-top; } .result { padding:0px; border: 1px solid #000000; margin:0px; background-color: #ffffff; width:100%; } .result a { text-decoration: none; color: #469AF8; } .result a:hover { color: #ff6633; } .input_box{ margin-bottom : 2px; } .mini_se { border: none 0; border-top: 1px dashed #717171; height: 1px; } .a_name a { color:#469AF8; width:130px; } .rsslink { text-decoration: none; color:#F88017; /* could be fancy, see : http://www.feedicons.com/ for icons*/ /*background-image: url("rss.png"); text-indent: -9999px;*/ } .purebibtex { font-family: monospace; font-size: small; border: 1px solid #DDDDDD; background: none repeat scroll 0 0 #F5F5F5; padding:10px; overflow:auto; width:600px; clear:both; } .bibentry-by { font-style: italic; } .bibentry-abstract { margin:15px; } .bibentry-label { margin-top:15px; } .bibentry-reference { margin-bottom:15px; padding:10px; background: none repeat scroll 0 0 #F5F5F5; border: 1px solid #DDDDDD; } .btb-nav { text-align: right; } <BODY> and TITLE) usage:
      $db = zetDB('metrics.bib');
      $dis = new BibEntryDisplay($db->getEntryByKey('Schmietendorf2000'));
      new HTMLWrapper($dis);
    
    */ class HTMLWrapper { /** * $content: an object with methods display() getRSS() getTitle() * $title: title of the page */ function HTMLWrapper(&$content,$metatags=array()/* an array name=>value*/) { // when we load a page with AJAX // the HTTP header is taken into account, not the header('Content-type: text/html; charset='.ENCODING); echo ''."\n"; ?> getRSS()!='') echo ''; ?> '."\n"; } // end foreach // now the title if (method_exists($content, 'getTitle')) { echo ''.strip_tags($content->getTitle()).''; } // now the CSS echo ''; ?> " . $content->getTitle() . ""; } ?> display(); echo poweredby(); if (BIBTEXBROWSER_USE_PROGRESSIVE_ENHANCEMENT) { javascript(); } ?> $db = zetDB('metrics.bib'); $dis = new SimpleDisplay($db); new NoWrapper($dis); */ class NoWrapper { function NoWrapper(&$content) { echo $content->display(); } } /** is used to create an subset of a bibtex file. usage:
      $db = zetDB('metrics.bib');
      $query = array('year'=>2005);
      $dis = new BibtexDisplay()->setEntries($db->multisearch($query));
      $dis->display();
    
    */ class BibtexDisplay { function BibtexDisplay() {} function setTitle($title) { $this->title = $title; return $this; } /** 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 '% generated by bibtexbrowser '."\n"; echo '% '.@$this->title."\n"; echo '% Encoding: '.ENCODING."\n"; foreach($this->entries as $bibentry) { echo $bibentry->getText()."\n"; } exit; } } /** creates paged output, e.g: [[http://localhost/bibtexbrowser/testPagedDisplay.php?page=1]] usage:
      $_GET['library']=1;
      include( 'bibtexbrowser.php' );
      $db = zetDB('metrics.bib');
      $pd = new PagedDisplay();
      $pd->setEntries($db->bibdb);
      $pd->display();
    
    */ class PagedDisplay { var $query = array(); function PagedDisplay() { $this->setPage(); } /** sets the entries to be shown */ function setEntries(&$entries) { uasort($entries, ORDER_FUNCTION); $this->entries = array_values($entries); } /** sets $this->page from $_GET, defaults to 1 */ function setPage() { $this->page = 1; if (isset($_GET['page'])) { $this->page = $_GET['page']; } } function setQuery($query = array()) { $this->query = $query; } function getTitle() { return query2title($this->query). ' - page '.$this->page; } function display() { $less = false; if ($this->page>1) {$less = true;} $more = true; // computing $more $index = ($this->page)*PAGE_SIZE; if (!isset($this->entries[$index])) { $more = false; } $this->menu($less, $more); $tag = 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($tag); $this->menu($less, $more); } function menu($less, $more) { echo ''; $prev = $this->query; $prev['page'] = $this->page-1; if ($less == true) { echo 'Prev Page'; } if ($less && $more) { echo ' | '; } $next = $this->query; $next['page'] = $this->page+1; if ($more == true) { echo 'Next Page'; } echo ''; } } /** is used to create an RSS feed. usage:
      $db = zetDB('metrics.bib');
      $query = array('year'=>2005);
      $rss = new RSSDisplay();
      $entries = $db->getLatestEntries(10);
      $rss->setEntries($entries);
      $rss->display();
    
    */ class RSSDisplay { 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 */ function text2rss($desc) { // first strip HTML tags $desc = strip_tags($desc); // then decode characters encoded by latex2html $desc= html_entity_decode($desc); // some entities may still be here, we remove them // we replace html entities e.g. é by nothing // however XML entities are kept (e.g. 5) $desc = preg_replace('/&\w+;/','',$desc); // bullet proofing ampersand $desc = preg_replace('/&([^#])/','&$1',$desc); // be careful of < $desc = str_replace('<','<',$desc); // final test with encoding: if (function_exists('mb_check_encoding')) { // (PHP 4 >= 4.4.3, PHP 5 >= 5.1.3) if (!mb_check_encoding($desc,ENCODING)) { return 'encoding error: please check the content of ENCODING'; } } 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 ''; // ?> <?php echo $this->title;?> http:// bibtexbrowser v20121205 entries as $bibentry) { ?> <?php echo $this->text2rss($bibentry->getTitle());?> getAbsoluteURL();?> text2rss(bib2html($bibentry)."\n".$bibentry->getAbstract()); ?> getKey());?> $_GET['library']=1; @require('bibtexbrowser.php'); // simulating ?bib=metrics.bib&year=2009 $_GET['bib']='metrics.bib'; $_GET['year']='2006'; $x = new Dispatcher(); $x->main(); */ class Dispatcher { /** this is the query */ var $query = array(); /** the displayer of selected entries. The default is set in BIBTEXBROWSER_DEFAULT_DISPLAY. * It could also be an RSSDisplay if the rss keyword is present */ 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 main() { // are we in test mode, or libray mode // then this file is just a library if (isset($_GET['test']) || isset($_GET['library'])) { // we unset in order to use the dispatcher afterwards unset($_GET['test']); unset($_GET['library']); return; } // first we set the database (load from disk or parse the bibtex file) 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=BIBTEXBROWSER_EMBEDDED_WRAPPER; // first pass, we will exit if we encounter key or menu or academic // other wise we just create the $this->query foreach($_GET as $keyword=>$value) { if (method_exists($this,$keyword)) { // if the return value is END_DISPATCH, we finish bibtexbrowser (but not the whole PHP process in case we are embedded) if ($this->$keyword()=='END_DISPATCH') return; } } // at this point, we may have a query if (count($this->query)>0) { // first test for inconsistent queries if (isset($this->query[Q_ALL]) && count($this->query)>1) { // we discard the Q_ALL, it helps in embedded mode unset($this->query[Q_ALL]); } $selectedEntries = $_GET[Q_DB]->multisearch($this->query); if (count($selectedEntries)==0) { $this->displayer = 'NotFoundDisplay'; } // default order uasort($selectedEntries, ORDER_FUNCTION); $selectedEntries = array_values($selectedEntries); //echo '
    ';print_r($selectedEntries);echo '
    '; if ($this->displayer=='') { $this->displayer = BIBTEXBROWSER_DEFAULT_DISPLAY; } } // otherwise the query is left empty // do we have a displayer? if ($this->displayer!='') { $options = array(); if (isset($_GET['dopt'])) { $options = json_decode($_GET['dopt'],true); } // required for PHP4 to have this intermediate variable $x = new $this->displayer(); if (method_exists($x,'setEntries')) { $x->setEntries($selectedEntries); } if (method_exists($x,'setTitle')) { $x->setTitle(query2title($this->query)); } if (method_exists($x,'setQuery')) { $x->setQuery($this->query); } // should call method display() on $x new $this->wrapper($x); $this->clearQuery(); } else { // we send a redirection for having the frameset // if some contents have already been sent, for instance if we are included // this means doing nothing if ( headers_sent() == false ) { /* to avoid sending an unnecessary frameset */ header("Location: ".$_SERVER['SCRIPT_NAME']."?frameset&bib=".$_GET[Q_FILE]); } } } /** 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'; } function astext() { $this->displayer='BibtexDisplay'; $this->wrapper='NoWrapper'; } function search() { if (preg_match('/utf-?8/i',ENCODING)) { $_GET[Q_SEARCH] = urldecode($_GET[Q_SEARCH]); } $this->query[Q_SEARCH]=$_GET[Q_SEARCH]; } function exclude() { $this->query[Q_EXCLUDE]=$_GET[Q_EXCLUDE]; } function year() { // we may want the latest if ($_GET[Q_YEAR]=='latest') { $years = $_GET[Q_DB]->yearIndex(); $_GET[Q_YEAR]=array_shift($years); } $this->query[Q_YEAR]=$_GET[Q_YEAR]; } function editor() { $this->query[EDITOR]=$_GET[EDITOR]; } function keywords() { $this->query[Q_TAG]=$_GET[Q_TAG]; } function author() { // Friday, October 29 2010 // changed from 'author' to '_author' // in order to search at the same time "Joe Dupont" an "Dupont, Joe" $this->query[Q_INNER_AUTHOR]=$_GET[Q_AUTHOR]; } function type() { $this->query[Q_TYPE]= $_GET[Q_TYPE]; } function menu() { $menu = createMenuManager(); $menu->setDB($_GET[Q_DB]); new $this->wrapper($menu,array(array('robots','noindex'))); return 'END_DISPATCH'; } /** the academic keyword in URLs switch from a year based viey to a publication type based view */ function academic() { $this->displayer='AcademicDisplay'; // backward compatibility with old GET API // this is deprecated // instead of academic=Martin+Monperrus // you should use author=Martin+Monperrus&academic // be careful of the semantics of === and !== // 'foo bar' == true is true // 123 == true is true (and whatever number different from 0 // 0 == true is true // '1'!=1 is **false** if(!isset($_GET[Q_AUTHOR]) && $_GET[Q_ACADEMIC]!==true && $_GET[Q_ACADEMIC]!=='true' && $_GET[Q_ACADEMIC]!=1 && $_GET[Q_ACADEMIC]!='') { $_GET[Q_AUTHOR]=$_GET[Q_ACADEMIC]; $this->query[Q_AUTHOR]=$_GET[Q_ACADEMIC]; } } function key() { if ($_GET[Q_DB]->contains($_GET[Q_KEY])) { $bibentry = $_GET[Q_DB]->getEntryByKey($_GET[Q_KEY]); $entries = array($bibentry); if (isset($_GET['astext'])) { $bibdisplay = new BibtexDisplay(); $bibdisplay->setEntries($entries); $bibdisplay->display(); } else { $bibdisplay = createBibEntryDisplay(); $bibdisplay->setEntries($entries); new $this->wrapper($bibdisplay,$bibdisplay->metadata()); } return 'END_DISPATCH'; } else { nonExistentBibEntryError(); } } /** 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 "dir: ".decoct(fileperms(dirname(__FILE__)))."\n"; echo "bibtex file: ".decoct(fileperms($_GET[Q_FILE]))."\n"; exit; } function frameset() { ?> You are browsing <?php echo $_GET[Q_FILE]; ?> with bibtexbrowser main(); ?>