diff --git a/src/BibDBBuilder.php b/src/BibDBBuilder.php
new file mode 100644
index 0000000..3939734
--- /dev/null
+++ b/src/BibDBBuilder.php
@@ -0,0 +1,161 @@
+
+ $empty_array = array();
+ $db = new BibDBBuilder(); // see also factory method createBibDBBuilder
+ $db->build('bibacid-utf8.bib'); // parses bib file
+ 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 extends ParserDelegate {
+
+ /** A hashtable from keys to bib entries (BibEntry). */
+ var $builtdb = array();
+
+ /** A hashtable of constant strings */
+ var $stringdb = array();
+
+ var $filename;
+
+ var $currentEntry;
+
+ function build($bibfilename, $handle = NULL) {
+
+ $this->filename = $bibfilename;
+ if ($handle == NULL) {
+ $handle = fopen($bibfilename, "r");
+ }
+
+ if (!$handle) die ('cannot open '.$bibfilename);
+
+ $parser = new StateBasedBibtexParser($this);
+ $parser->parse($handle);
+ fclose($handle);
+ //print_r(array_keys($this->builtdb));
+ //print_r($this->builtdb);
+ }
+
+
+ function getBuiltDb() {
+ //print_r($this->builtdb);
+ return $this->builtdb;
+ }
+
+ function beginFile() {
+ }
+
+ function endFile() {
+ // resolving crossrefs
+ // we are careful with PHP 4 semantics
+ foreach (array_keys($this->builtdb) as $key) {
+ $bib = $this->builtdb[$key];
+ if ($bib->hasField('crossref')) {
+ if (isset($this->builtdb[$bib->getField('crossref')])) {
+ $crossrefEntry = $this->builtdb[$bib->getField('crossref')];
+ $bib->crossref = $crossrefEntry;
+ foreach($crossrefEntry->getFields() as $k => $v) {
+ // copying the fields of the cross ref
+ // only if they don't exist yet
+ if (!$bib->hasField($k)) {
+ $bib->setField($k,$v);
+ }
+ }
+ }
+ }
+ }
+ //print_r($this->builtdb);
+ }
+
+ function setEntryField($fieldkey,$entryvalue) {
+ $fieldkey=trim($fieldkey);
+ // support for Bibtex concatenation
+ // see http://newton.ex.ac.uk/tex/pack/bibtex/btxdoc/node3.html
+ // (?$v) {
+ // spaces are allowed when using # and they are not taken into account
+ // however # is not itself replaced by a space
+ // warning: @strings are not case sensitive
+ // see http://newton.ex.ac.uk/tex/pack/bibtex/btxdoc/node3.html
+ $stringKey=strtolower(trim($v));
+ if (isset($this->stringdb[$stringKey]))
+ {
+ // this field will be formated later by xtrim and latex2html
+ $entryvalue_array[$k]=$this->stringdb[$stringKey]->value;
+
+ // we keep a trace of this replacement
+ // so as to produce correct bibtex snippets
+ $this->currentEntry->constants[$stringKey]=$this->stringdb[$stringKey]->value;
+ }
+ }
+ $entryvalue=implode('',$entryvalue_array);
+
+ $this->currentEntry->setField($fieldkey,$entryvalue);
+ }
+
+ function setEntryType($entrytype) {
+ $this->currentEntry->setType($entrytype);
+ }
+
+ function setEntryKey($entrykey) {
+ //echo "new entry:".$entrykey."\n";
+ $this->currentEntry->setKey($entrykey);
+ }
+
+ function beginEntry() {
+ $this->currentEntry = createBibEntry();
+ $this->currentEntry->setFile($this->filename);
+ }
+
+ function endEntry($entrysource) {
+
+ // we add a timestamp
+ $this->currentEntry->timestamp();
+
+ // we add a key if there is no key
+ if (!$this->currentEntry->hasField(Q_KEY) && $this->currentEntry->getType()!='string') {
+ $this->currentEntry->setField(Q_KEY,md5($entrysource));
+ }
+
+ // 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(Q_INNER_AUTHOR,$this->currentEntry->getFormattedAuthorsString());
+
+ foreach($this->currentEntry->getCanonicalAuthors() as $author) {
+ $homepage_key = $this->currentEntry->getHomePageKey($author);
+ if (isset($this->stringdb[$homepage_key])) {
+ $this->currentEntry->homepages[$homepage_key] = $this->stringdb[$homepage_key]->value;
+ }
+ }
+ }
+
+ // ignoring jabref comments
+ if (($this->currentEntry->getType()=='comment')) {
+ /* do nothing for jabref comments */
+ }
+
+ // we add it to the string database
+ else if ($this->currentEntry->getType()=='string') {
+ foreach($this->currentEntry->fields as $k => $v) {
+ $k!=Q_INNER_TYPE and $this->stringdb[$k] = new StringEntry($k,$v,$this->filename);
+ }
+ }
+
+ // we add it to the database
+ else {
+ $this->builtdb[$this->currentEntry->getKey()] = $this->currentEntry;
+ }
+ }
+
+} // end class BibDBBuilder
diff --git a/src/Definitions.php b/src/Definitions.php
index 46506a5..65d8c9d 100644
--- a/src/Definitions.php
+++ b/src/Definitions.php
@@ -2,188 +2,194 @@
namespace Monperrus\BibtexBrowser;
-// the encoding of your bibtex file
-@define('BIBTEX_INPUT_ENCODING','UTF-8');//@define('BIBTEX_INPUT_ENCODING','iso-8859-1');//define('BIBTEX_INPUT_ENCODING','windows-1252');
-// the encoding of the HTML output
-@define('OUTPUT_ENCODING','UTF-8');
-
-// print a warning if deprecated variable is used
-if (defined('ENCODING')) {
- echo 'ENCODING has been replaced by BIBTEX_INPUT_ENCODING and OUTPUT_ENCODING';
+class Definitions
+{
+ public function __construct()
+ {
+ // the encoding of your bibtex file
+ @define('BIBTEX_INPUT_ENCODING','UTF-8');//@define('BIBTEX_INPUT_ENCODING','iso-8859-1');//define('BIBTEX_INPUT_ENCODING','windows-1252');
+ // the encoding of the HTML output
+ @define('OUTPUT_ENCODING','UTF-8');
+
+ // print a warning if deprecated variable is used
+ if (defined('ENCODING')) {
+ echo 'ENCODING has been replaced by BIBTEX_INPUT_ENCODING and OUTPUT_ENCODING';
+ }
+
+ // 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);
+ @define('BIBLIOGRAPHYSTYLE','DefaultBibliographyStyle');// this is the name of a function
+ @define('BIBLIOGRAPHYSECTIONS','DefaultBibliographySections');// this is the name of a function
+ @define('BIBLIOGRAPHYTITLE','DefaultBibliographyTitle');// this is the name of a function
+
+ // shall we load MathJax to render math in $…$ in HTML?
+ @define('BIBTEXBROWSER_RENDER_MATH', true);
+ @define('MATHJAX_URI', '//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML.js');
+
+ // the default jquery URI
+ @define('JQUERY_URI', '//code.jquery.com/jquery-1.5.1.min.js');
+
+ // 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 default template
+ @define('BIBTEXBROWSER_DEFAULT_TEMPLATE','HTMLTemplate');
+
+ // 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/keys-index
+
+ // are robots allowed to crawl and index bibtexbrowser generated pages?
+ @define('BIBTEXBROWSER_ROBOTS_NOINDEX',false);
+
+ //the default view in the "main" (right hand side) frame
+ @define('BIBTEXBROWSER_DEFAULT_FRAME','year=latest'); // year=latest,all and all valid bibtexbrowser queries
+
+ // Wrapper to use when we are included by another script
+ @define('BIBTEXBROWSER_EMBEDDED_WRAPPER', 'NoWrapper');
+
+ // Main class to use
+ @define('BIBTEXBROWSER_MAIN', 'Dispatcher');
+
+ // default order functions
+ // Contract Returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.
+ // can be @define('ORDER_FUNCTION','compare_bib_entry_by_title');
+ // can be @define('ORDER_FUNCTION','compare_bib_entry_by_bibtex_order');
+ @define('ORDER_FUNCTION','compare_bib_entry_by_year');
+ @define('ORDER_FUNCTION_FINE','compare_bib_entry_by_month');
+
+ // only displaying the n newest entries
+ @define('BIBTEXBROWSER_NEWEST',5);
+
+ @define('BIBTEXBROWSER_NO_DEFAULT', false);
+
+ // BIBTEXBROWSER_LINK_STYLE defines which function to use to display the links of a bibtex entry
+ @define('BIBTEXBROWSER_LINK_STYLE','bib2links_default'); // can be 'nothing' (a function that does nothing)
+
+ // do we add [bibtex] links ?
+ @define('BIBTEXBROWSER_BIBTEX_LINKS',true);
+ // do we add [pdf] links ?
+ @define('BIBTEXBROWSER_PDF_LINKS',true);
+ // do we add [doi] links ?
+ @define('BIBTEXBROWSER_DOI_LINKS',true);
+ // do we add [gsid] links (Google Scholar)?
+ @define('BIBTEXBROWSER_GSID_LINKS',true);
+
+ // should pdf, doi, url, gsid links be opened in a new window?
+ @define('BIBTEXBROWSER_LINKS_TARGET','_self');// can be _blank (new window), _top (with frames)
+
+ // 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');
+
+ // BIBTEXBROWSER_LAYOUT defines the HTML rendering layout of the produced HTML
+ // may be table/list/ordered_list/definition/none (for
, , , nothing resp.).
+ // for list/ordered_list, the abbrevations are not taken into account (see ABBRV_TYPE)
+ // for ordered_list, the index is given by HTML directly (in increasing order)
+ @define('BIBTEXBROWSER_LAYOUT','table');
+
+ // should the original bibtex be displayed or a reconstructed one with filtering
+ // values: original/reconstructed
+ // warning, with reconstructed, the latex markup for accents/diacritics is lost
+ @define('BIBTEXBROWSER_BIBTEX_VIEW','original');
+ // a list of fields that will not be shown in the bibtex view if BIBTEXBROWSER_BIBTEX_VIEW=reconstructed
+ @define('BIBTEXBROWSER_BIBTEX_VIEW_FILTEREDOUT','comment|note|file');
+
+ // should Latex macros be executed (e.g. \'e -> é
+ @define('BIBTEXBROWSER_USE_LATEX2HTML',true);
+
+ // Which is the first html level that should be used in embedded mode?
+ @define('BIBTEXBROWSER_HTMLHEADINGLEVEL', 2);
+
+ @define('BIBTEXBROWSER_ACADEMIC_TOC', false);
+
+ @define('BIBTEXBROWSER_DEBUG',false);
+
+ // how to print authors names?
+ // default => as in the bibtex file
+ // USE_COMMA_AS_NAME_SEPARATOR_IN_OUTPUT = true => "Meyer, Herbert"
+ // USE_INITIALS_FOR_NAMES = true => "Meyer H"
+ // USE_FIRST_THEN_LAST => Herbert Meyer
+ @define('USE_COMMA_AS_NAME_SEPARATOR_IN_OUTPUT',false);// output authors in a comma separated form, e.g. "Meyer, H"?
+ @define('USE_INITIALS_FOR_NAMES',false); // use only initials for all first names?
+ @define('USE_FIRST_THEN_LAST',false); // use only initials for all first names?
+ @define('FORCE_NAMELIST_SEPARATOR', ''); // if non-empty, use this to separate multiple names regardless of USE_COMMA_AS_NAME_SEPARATOR_IN_OUTPUT
+ @define('LAST_AUTHOR_SEPARATOR',' and ');
+
+ @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_YEAR_INPRESS', 'in press');
+ @define('Q_YEAR_ACCEPTED', 'accepted');
+ @define('Q_YEAR_SUBMITTED', 'submitted');
+ @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_KEYS', 'keys'); // filter entries using a url-encoded, JSON-encoded array of bibtex keys
+ @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('Q_RANGE', 'range');
+ @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_OPENGRAPH',true);
+ @define('METADATA_EPRINTS',false);
+
+ // define sort order for special values in 'year' field
+ // highest number is sorted first
+ // don't exceed 0 though, since the values are added to PHP_INT_MAX
+ @define('ORDER_YEAR_INPRESS', -0);
+ @define('ORDER_YEAR_ACCEPTED', -1);
+ @define('ORDER_YEAR_SUBMITTED', -2);
+ @define('ORDER_YEAR_OTHERNONINT', -3);
+
+
+ // 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
+ // for instance with @define('BIBTEXBROWSER_URL',''); // links to the current page with ?
+ //@define('BIBTEXBROWSER_URL',basename(__FILE__));
+ @define('BIBTEXBROWSER_URL',parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
+
+ // *************** 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
+ @define('Q_INNER_KEYS_INDEX', '_keys-index');// used for storing indices in $_GET[Q_KEYS] array
+ }
}
-
-// 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);
-@define('BIBLIOGRAPHYSTYLE','DefaultBibliographyStyle');// this is the name of a function
-@define('BIBLIOGRAPHYSECTIONS','DefaultBibliographySections');// this is the name of a function
-@define('BIBLIOGRAPHYTITLE','DefaultBibliographyTitle');// this is the name of a function
-
-// shall we load MathJax to render math in $…$ in HTML?
-@define('BIBTEXBROWSER_RENDER_MATH', true);
-@define('MATHJAX_URI', '//cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS_HTML.js');
-
-// the default jquery URI
-@define('JQUERY_URI', '//code.jquery.com/jquery-1.5.1.min.js');
-
-// 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 default template
-@define('BIBTEXBROWSER_DEFAULT_TEMPLATE','HTMLTemplate');
-
-// 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/keys-index
-
-// are robots allowed to crawl and index bibtexbrowser generated pages?
-@define('BIBTEXBROWSER_ROBOTS_NOINDEX',false);
-
-//the default view in the "main" (right hand side) frame
-@define('BIBTEXBROWSER_DEFAULT_FRAME','year=latest'); // year=latest,all and all valid bibtexbrowser queries
-
-// Wrapper to use when we are included by another script
-@define('BIBTEXBROWSER_EMBEDDED_WRAPPER', 'NoWrapper');
-
-// Main class to use
-@define('BIBTEXBROWSER_MAIN', 'Dispatcher');
-
-// default order functions
-// Contract Returns < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal.
-// can be @define('ORDER_FUNCTION','compare_bib_entry_by_title');
-// can be @define('ORDER_FUNCTION','compare_bib_entry_by_bibtex_order');
-@define('ORDER_FUNCTION','compare_bib_entry_by_year');
-@define('ORDER_FUNCTION_FINE','compare_bib_entry_by_month');
-
-// only displaying the n newest entries
-@define('BIBTEXBROWSER_NEWEST',5);
-
-@define('BIBTEXBROWSER_NO_DEFAULT', false);
-
-// BIBTEXBROWSER_LINK_STYLE defines which function to use to display the links of a bibtex entry
-@define('BIBTEXBROWSER_LINK_STYLE','bib2links_default'); // can be 'nothing' (a function that does nothing)
-
-// do we add [bibtex] links ?
-@define('BIBTEXBROWSER_BIBTEX_LINKS',true);
-// do we add [pdf] links ?
-@define('BIBTEXBROWSER_PDF_LINKS',true);
-// do we add [doi] links ?
-@define('BIBTEXBROWSER_DOI_LINKS',true);
-// do we add [gsid] links (Google Scholar)?
-@define('BIBTEXBROWSER_GSID_LINKS',true);
-
-// should pdf, doi, url, gsid links be opened in a new window?
-@define('BIBTEXBROWSER_LINKS_TARGET','_self');// can be _blank (new window), _top (with frames)
-
-// 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');
-
-// BIBTEXBROWSER_LAYOUT defines the HTML rendering layout of the produced HTML
-// may be table/list/ordered_list/definition/none (for , , , nothing resp.).
-// for list/ordered_list, the abbrevations are not taken into account (see ABBRV_TYPE)
-// for ordered_list, the index is given by HTML directly (in increasing order)
-@define('BIBTEXBROWSER_LAYOUT','table');
-
-// should the original bibtex be displayed or a reconstructed one with filtering
-// values: original/reconstructed
-// warning, with reconstructed, the latex markup for accents/diacritics is lost
-@define('BIBTEXBROWSER_BIBTEX_VIEW','original');
-// a list of fields that will not be shown in the bibtex view if BIBTEXBROWSER_BIBTEX_VIEW=reconstructed
-@define('BIBTEXBROWSER_BIBTEX_VIEW_FILTEREDOUT','comment|note|file');
-
-// should Latex macros be executed (e.g. \'e -> é
-@define('BIBTEXBROWSER_USE_LATEX2HTML',true);
-
-// Which is the first html level that should be used in embedded mode?
-@define('BIBTEXBROWSER_HTMLHEADINGLEVEL', 2);
-
-@define('BIBTEXBROWSER_ACADEMIC_TOC', false);
-
-@define('BIBTEXBROWSER_DEBUG',false);
-
-// how to print authors names?
-// default => as in the bibtex file
-// USE_COMMA_AS_NAME_SEPARATOR_IN_OUTPUT = true => "Meyer, Herbert"
-// USE_INITIALS_FOR_NAMES = true => "Meyer H"
-// USE_FIRST_THEN_LAST => Herbert Meyer
-@define('USE_COMMA_AS_NAME_SEPARATOR_IN_OUTPUT',false);// output authors in a comma separated form, e.g. "Meyer, H"?
-@define('USE_INITIALS_FOR_NAMES',false); // use only initials for all first names?
-@define('USE_FIRST_THEN_LAST',false); // use only initials for all first names?
-@define('FORCE_NAMELIST_SEPARATOR', ''); // if non-empty, use this to separate multiple names regardless of USE_COMMA_AS_NAME_SEPARATOR_IN_OUTPUT
-@define('LAST_AUTHOR_SEPARATOR',' and ');
-
-@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_YEAR_INPRESS', 'in press');
-@define('Q_YEAR_ACCEPTED', 'accepted');
-@define('Q_YEAR_SUBMITTED', 'submitted');
-@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_KEYS', 'keys'); // filter entries using a url-encoded, JSON-encoded array of bibtex keys
-@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('Q_RANGE', 'range');
-@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_OPENGRAPH',true);
-@define('METADATA_EPRINTS',false);
-
-// define sort order for special values in 'year' field
-// highest number is sorted first
-// don't exceed 0 though, since the values are added to PHP_INT_MAX
-@define('ORDER_YEAR_INPRESS', -0);
-@define('ORDER_YEAR_ACCEPTED', -1);
-@define('ORDER_YEAR_SUBMITTED', -2);
-@define('ORDER_YEAR_OTHERNONINT', -3);
-
-
-// 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
-// for instance with @define('BIBTEXBROWSER_URL',''); // links to the current page with ?
-//@define('BIBTEXBROWSER_URL',basename(__FILE__));
-@define('BIBTEXBROWSER_URL',parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH));
-
-// *************** 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
-@define('Q_INNER_KEYS_INDEX', '_keys-index');// used for storing indices in $_GET[Q_KEYS] array
diff --git a/src/ParserDelegate.php b/src/ParserDelegate.php
new file mode 100644
index 0000000..629af5d
--- /dev/null
+++ b/src/ParserDelegate.php
@@ -0,0 +1,27 @@
+delegate = $delegate;
+ }
+
+ public function parse($handle) {
+ if (gettype($handle) == 'string') { throw new Exception('oops'); }
+ $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='';
+ $fieldvaluepart='';
+ $finalkey='';
+ $entrysource='';
+
+ // metastate
+ $isinentry = false;
+
+ $delegate->beginFile();
+
+ // 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;
+ $fieldvaluepart='';
+ $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($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($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;
+ $delegate->entryValuePart($finalkey,$fieldvaluepart,'CURLYTOP');
+ $fieldvaluepart='';
+ }
+ else if ($s=='}') { // end entry
+ $state = GETVALUE;
+ $delegate->entryValuePart($finalkey,$fieldvaluepart,'CURLYTOP');
+ }
+ else {
+ $entryvalue=$entryvalue.$s;
+ $fieldvaluepart=$fieldvaluepart.$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;
+ $delegate->entryValuePart($finalkey,$fieldvaluepart,'CURLYONE');
+ $fieldvaluepart='';
+ $entryvalue=$entryvalue.$s;
+ }
+ else {
+ $entryvalue=$entryvalue.$s;
+ $fieldvaluepart=$fieldvaluepart.$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) {
+
+ 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();
+ //$d = $this->delegate;print_r($d);
+ } // end function
+} // end class
diff --git a/src/StringEntry.php b/src/StringEntry.php
new file mode 100644
index 0000000..0f54186
--- /dev/null
+++ b/src/StringEntry.php
@@ -0,0 +1,19 @@
+name=$key;
+ $this->value=$value;
+ $this->filename=$filename;
+ }
+
+ public function toString()
+ {
+ return '@string{'.$this->name.'={'.$this->value.'}}';
+ }
+} // end class StringEntry
diff --git a/src/XMLPrettyPrinter.php b/src/XMLPrettyPrinter.php
new file mode 100644
index 0000000..ce414f3
--- /dev/null
+++ b/src/XMLPrettyPrinter.php
@@ -0,0 +1,40 @@
+';
+ print '';
+ }
+
+ public function endFile() {
+ print '';
+ }
+
+ public function setEntryField($finalkey,$entryvalue) {
+ print "\n".$finalkey."\n".$entryvalue."\n\n";
+ }
+
+ public function setEntryType($entrytype) {
+ print ''.$entrytype.'';
+ }
+
+ public function setEntryKey($entrykey) {
+ print ''.$entrykey.'';
+ }
+
+ public function beginEntry() {
+ print "\n";
+ }
+
+ public function endEntry($entrysource) {
+ print "\n";
+ }
+} // end class XMLPrettyPrinter
diff --git a/src/bibtexbrowser.php b/src/bibtexbrowser.php
old mode 100755
new mode 100644
index e3aae03..681d260
--- a/src/bibtexbrowser.php
+++ b/src/bibtexbrowser.php
@@ -15,6 +15,12 @@ License, or (at your option) any later version.
*/
+use Monperrus\BibtexBrowser\StateBasedBibtexParser;
+use Monperrus\BibtexBrowser\ParserDelegate;
+use Monperrus\BibtexBrowser\XMLPrettyPrinter;
+use Monperrus\BibtexBrowser\StringEntry;
+use Monperrus\BibtexBrowser\BibDBBuilder;
+
// 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')) {
@@ -483,471 +489,10 @@ 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 __construct($delegate) {
- $this->delegate = $delegate;
- }
-
- function parse($handle) {
- if (gettype($handle) == 'string') { throw new Exception('oops'); }
- $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='';
- $fieldvaluepart='';
- $finalkey='';
- $entrysource='';
-
- // metastate
- $isinentry = false;
-
- $delegate->beginFile();
-
- // 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;
- $fieldvaluepart='';
- $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($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($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;
- $delegate->entryValuePart($finalkey,$fieldvaluepart,'CURLYTOP');
- $fieldvaluepart='';
- }
- else if ($s=='}') { // end entry
- $state = GETVALUE;
- $delegate->entryValuePart($finalkey,$fieldvaluepart,'CURLYTOP');
- }
- else {
- $entryvalue=$entryvalue.$s;
- $fieldvaluepart=$fieldvaluepart.$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;
- $delegate->entryValuePart($finalkey,$fieldvaluepart,'CURLYONE');
- $fieldvaluepart='';
- $entryvalue=$entryvalue.$s;
- }
- else {
- $entryvalue=$entryvalue.$s;
- $fieldvaluepart=$fieldvaluepart.$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) {
-
- 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();
- //$d = $this->delegate;print_r($d);
- } // end function
-} // end class
-
-/** a default empty implementation of a delegate for StateBasedBibtexParser */
-class ParserDelegate {
-
- function beginFile() {}
-
- function endFile() {}
-
- function setEntryField($finalkey,$entryvalue) {}
-
- function setEntryType($entrytype) {}
-
- function setEntryKey($entrykey) {}
-
- function beginEntry() {}
-
- function endEntry($entrysource) {}
-
- /** called for each sub parts of type {part} of a field value
- * for now, only CURLYTOP and CURLYONE events
- */
- function entryValuePart($key, $value, $type) {}
-
-} // end class ParserDelegate
-
-
-/** is a possible delegate for StateBasedBibParser.
-usage:
-see snippet of [[#StateBasedBibParser]]
-*/
-class XMLPrettyPrinter extends ParserDelegate {
- function beginFile() {
- header('Content-type: text/xml;');
- print '';
- print '';
- }
-
-
- function endFile() {
- print '';
- }
- function setEntryField($finalkey,$entryvalue) {
- print "\n".$finalkey."\n".$entryvalue."\n\n";
- }
-
- function setEntryType($entrytype) {
- print ''.$entrytype.'';
- }
- function setEntryKey($entrykey) {
- print ''.$entrykey.'';
- }
-
- function beginEntry() {
- print "\n";
- }
-
- function endEntry($entrysource) {
- print "\n";
- }
-} // end class XMLPrettyPrinter
-
-/** represents @string{k=v} */
-class StringEntry {
- function __construct($k, $v, $filename) {
- $this->name=$k;
- $this->value=$v;
- $this->filename=$filename;
- }
-
- function toString() {
- return '@string{'.$this->name.'={'.$this->value.'}}';
- }
-} // end class StringEntry
-
-
-
-
-/** builds arrays of BibEntry objects from a bibtex file.
-usage:
-
- $empty_array = array();
- $db = new BibDBBuilder(); // see also factory method createBibDBBuilder
- $db->build('bibacid-utf8.bib'); // parses bib file
- 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 extends ParserDelegate {
-
- /** A hashtable from keys to bib entries (BibEntry). */
- var $builtdb = array();
-
- /** A hashtable of constant strings */
- var $stringdb = array();
-
- var $filename;
-
- var $currentEntry;
-
- function build($bibfilename, $handle = NULL) {
-
- $this->filename = $bibfilename;
- if ($handle == NULL) {
- $handle = fopen($bibfilename, "r");
- }
-
- if (!$handle) die ('cannot open '.$bibfilename);
-
- $parser = new StateBasedBibtexParser($this);
- $parser->parse($handle);
- fclose($handle);
- //print_r(array_keys($this->builtdb));
- //print_r($this->builtdb);
- }
-
-
- function getBuiltDb() {
- //print_r($this->builtdb);
- return $this->builtdb;
- }
-
- function beginFile() {
- }
-
- function endFile() {
- // resolving crossrefs
- // we are careful with PHP 4 semantics
- foreach (array_keys($this->builtdb) as $key) {
- $bib = $this->builtdb[$key];
- if ($bib->hasField('crossref')) {
- if (isset($this->builtdb[$bib->getField('crossref')])) {
- $crossrefEntry = $this->builtdb[$bib->getField('crossref')];
- $bib->crossref = $crossrefEntry;
- foreach($crossrefEntry->getFields() as $k => $v) {
- // copying the fields of the cross ref
- // only if they don't exist yet
- if (!$bib->hasField($k)) {
- $bib->setField($k,$v);
- }
- }
- }
- }
- }
- //print_r($this->builtdb);
- }
-
- function setEntryField($fieldkey,$entryvalue) {
- $fieldkey=trim($fieldkey);
- // support for Bibtex concatenation
- // see http://newton.ex.ac.uk/tex/pack/bibtex/btxdoc/node3.html
- // (?$v) {
- // spaces are allowed when using # and they are not taken into account
- // however # is not itself replaced by a space
- // warning: @strings are not case sensitive
- // see http://newton.ex.ac.uk/tex/pack/bibtex/btxdoc/node3.html
- $stringKey=strtolower(trim($v));
- if (isset($this->stringdb[$stringKey]))
- {
- // this field will be formated later by xtrim and latex2html
- $entryvalue_array[$k]=$this->stringdb[$stringKey]->value;
-
- // we keep a trace of this replacement
- // so as to produce correct bibtex snippets
- $this->currentEntry->constants[$stringKey]=$this->stringdb[$stringKey]->value;
- }
- }
- $entryvalue=implode('',$entryvalue_array);
-
- $this->currentEntry->setField($fieldkey,$entryvalue);
- }
-
- function setEntryType($entrytype) {
- $this->currentEntry->setType($entrytype);
- }
-
- function setEntryKey($entrykey) {
- //echo "new entry:".$entrykey."\n";
- $this->currentEntry->setKey($entrykey);
- }
-
- function beginEntry() {
- $this->currentEntry = createBibEntry();
- $this->currentEntry->setFile($this->filename);
- }
- function endEntry($entrysource) {
- // we add a timestamp
- $this->currentEntry->timestamp();
-
- // we add a key if there is no key
- if (!$this->currentEntry->hasField(Q_KEY) && $this->currentEntry->getType()!='string') {
- $this->currentEntry->setField(Q_KEY,md5($entrysource));
- }
-
- // 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(Q_INNER_AUTHOR,$this->currentEntry->getFormattedAuthorsString());
-
- foreach($this->currentEntry->getCanonicalAuthors() as $author) {
- $homepage_key = $this->currentEntry->getHomePageKey($author);
- if (isset($this->stringdb[$homepage_key])) {
- $this->currentEntry->homepages[$homepage_key] = $this->stringdb[$homepage_key]->value;
- }
- }
- }
-
- // ignoring jabref comments
- if (($this->currentEntry->getType()=='comment')) {
- /* do nothing for jabref comments */
- }
-
- // we add it to the string database
- else if ($this->currentEntry->getType()=='string') {
- foreach($this->currentEntry->fields as $k => $v) {
- $k!=Q_INNER_TYPE and $this->stringdb[$k] = new StringEntry($k,$v,$this->filename);
- }
- }
-
- // we add it to the database
- else {
- $this->builtdb[$this->currentEntry->getKey()] = $this->currentEntry;
- }
- }
-} // end class BibDBBuilder