* @copyright 1997-2005 The PHP Group
* @license http://www.php.net/license/3_0.txt PHP License 3.0
* @version Release: @package_version@
* @link http://pear.php.net/Structures/Structure_BibTex
*/
class Structures_BibTex
{
/**
* Array with the BibTex Data
*
* @access public
* @var array
*/
var $data;
/**
* String with the BibTex content
*
* @access public
* @var string
*/
var $content;
/**
* Array with possible Delimiters for the entries
*
* @access private
* @var array
*/
var $_delimiters;
/**
* Array to store warnings
*
* @access public
* @var array
*/
var $warnings;
/**
* Run-time configuration options
*
* @access private
* @var array
*/
var $_options;
/**
* RTF Format String
*
* @access public
* @var string
*/
var $rtfstring;
/**
* HTML Format String
*
* @access public
* @var string
*/
var $htmlstring;
/**
* Array with the "allowed" entry types
*
* @access public
* @var array
*/
var $allowedEntryTypes;
/**
* Author Format Strings
*
* @access public
* @var string
*/
var $authorstring;
/**
* Constructor
*
* @access public
* @return void
*/
function Structures_BibTex($options = array())
{
$this->_delimiters = array('"'=>'"',
'{'=>'}');
$this->data = array();
$this->content = '';
//$this->_stripDelimiter = $stripDel;
//$this->_validate = $val;
$this->warnings = array();
$this->_options = array(
'stripDelimiter' => true,
'validate' => true,
'unwrap' => false,
'wordWrapWidth' => false,
'wordWrapBreak' => "\n",
'wordWrapCut' => 0,
'removeCurlyBraces' => false,
'extractAuthors' => true,
);
foreach ($options as $option => $value) {
$test = $this->setOption($option, $value);
if (PEAR::isError($test)) {
//Currently nothing is done here, but it could for example raise an warning
}
}
$this->rtfstring = 'AUTHORS, "{\b TITLE}", {\i JOURNAL}, YEAR';
$this->htmlstring = 'AUTHORS, "TITLE", JOURNAL, YEAR
';
$this->allowedEntryTypes = array(
'article',
'book',
'booklet',
'conference',
'inbook',
'incollection',
'inproceedings',
'manual',
'mastersthesis',
'misc',
'phdthesis',
'proceedings',
'techreport',
'unpublished'
);
$this->authorstring = 'VON LAST, JR, FIRST';
}
/**
* Sets run-time configuration options
*
* @access public
* @param string $option option name
* @param mixed $value value for the option
* @return mixed true on success PEAR_Error on failure
*/
function setOption($option, $value)
{
$ret = true;
if (array_key_exists($option, $this->_options)) {
$this->_options[$option] = $value;
} else {
$ret = PEAR::raiseError('Unknown option '.$option);
}
return $ret;
}
/**
* Reads a given BibTex File
*
* @access public
* @param string $filename Name of the file
* @return mixed true on success PEAR_Error on failure
*/
function loadFile($filename)
{
if (file_exists($filename)) {
if (($this->content = @file_get_contents($filename)) === false) {
return PEAR::raiseError('Could not open file '.$filename);
} else {
$this->_pos = 0;
$this->_oldpos = 0;
return true;
}
} else {
return PEAR::raiseError('Could not find file '.$filename);
}
}
/**
* Reads bibtex from a string variable
*
* @access public
* @param string $bib String containing bibtex
* @return boolean true
*/
function loadString($bib)
{
$this->content = $bib;
$this->_pos = 0;
$this->_oldpos = 0;
return true; // For compatibility with loadFile
}
/**
* Parses what is stored in content and clears the content if the parsing is successfull.
*
* @access public
* @return boolean true on success and PEAR_Error if there was a problem
*/
function parse()
{
//The amount of opening braces is compared to the amount of closing braces
//Braces inside comments are ignored
$this->warnings = array();
$this->data = array();
$valid = true;
$open = 0;
$entry = false;
$char = '';
$lastchar = '';
$buffer = '';
for ($i = 0; $i < strlen($this->content); $i++) {
$char = substr($this->content, $i, 1);
if ((0 != $open) && ('@' == $char)) {
if (!$this->_checkAt($buffer)) {
$this->_generateWarning('WARNING_MISSING_END_BRACE', '', $buffer);
//To correct the data we need to insert a closing brace
$char = '}';
$i--;
}
}
if ((0 == $open) && ('@' == $char)) { //The beginning of an entry
$entry = true;
} elseif ($entry && ('{' == $char) && ('\\' != $lastchar)) { //Inside an entry and non quoted brace is opening
$open++;
} elseif ($entry && ('}' == $char) && ('\\' != $lastchar)) { //Inside an entry and non quoted brace is closing
$open--;
if ($open < 0) { //More are closed than opened
$valid = false;
}
if (0 == $open) { //End of entry
$entry = false;
$entrydata = $this->_parseEntry($buffer);
if (!$entrydata) {
/**
* This is not yet used.
* We are here if the Entry is either not correct or not supported.
* But this should already generate a warning.
* Therefore it should not be necessary to do anything here
*/
} else {
$this->data[] = $entrydata;
}
$buffer = '';
}
}
if ($entry) { //Inside entry
$buffer .= $char;
}
$lastchar = $char;
}
//If open is one it may be possible that the last ending brace is missing
if (1 == $open) {
$entrydata = $this->_parseEntry($buffer);
if (!$entrydata) {
$valid = false;
} else {
$this->data[] = $entrydata;
$buffer = '';
$open = 0;
}
}
//At this point the open should be zero
if (0 != $open) {
$valid = false;
}
//Are there Multiple entries with the same cite?
if ($this->_options['validate']) {
$cites = array();
foreach ($this->data as $entry) {
$cites[] = $entry['cite'];
}
$unique = array_unique($cites);
if (sizeof($cites) != sizeof($unique)) { //Some values have not been unique!
$notuniques = array();
for ($i = 0; $i < sizeof($cites); $i++) {
if ('' == $unique[$i]) {
$notuniques[] = $cites[$i];
}
}
$this->_generateWarning('WARNING_MULTIPLE_ENTRIES', implode(',',$notuniques));
}
}
if ($valid) {
$this->content = '';
return true;
} else {
return PEAR::raiseError('Unbalanced parenthesis');
}
}
/**
* Extracting the data of one content
*
* The parse function splits the content into its entries.
* Then every entry is parsed by this function.
* It parses the entry backwards.
* First the last '=' is searched and the value extracted from that.
* A copy is made of the entry if warnings should be generated. This takes quite
* some memory but it is needed to get good warnings. If nor warnings are generated
* then you don have to worry about memory.
* Then the last ',' is searched and the field extracted from that.
* Again the entry is shortened.
* Finally after all field=>value pairs the cite and type is extraced and the
* authors are splitted.
* If there is a problem false is returned.
*
* @access private
* @param string $entry The entry
* @return array The representation of the entry or false if there is a problem
*/
function _parseEntry($entry)
{
$entrycopy = '';
if ($this->_options['validate']) {
$entrycopy = $entry; //We need a copy for printing the warnings
}
$ret = array('bibtex' => $entry.'}');
if ('@string' == strtolower(substr($entry, 0, 7))) {
//String are not yet supported!
if ($this->_options['validate']) {
$this->_generateWarning('STRING_ENTRY_NOT_YET_SUPPORTED', '', $entry.'}');
}
} elseif ('@preamble' == strtolower(substr($entry, 0, 9))) {
//Preamble not yet supported!
if ($this->_options['validate']) {
$this->_generateWarning('PREAMBLE_ENTRY_NOT_YET_SUPPORTED', '', $entry.'}');
}
} else {
// Look for key
$matches = array();
preg_match('/^@\w+\{(.+?),/' ,$entry, $matches);
if ( count($matches) > 0 )
{
$ret['entrykey'] = $matches[1];
}
//Parsing all fields
while (strrpos($entry,'=') !== false) {
$position = strrpos($entry, '=');
//Checking that the equal sign is not quoted or is not inside a equation (For example in an abstract)
$proceed = true;
if (substr($entry, $position-1, 1) == '\\') {
$proceed = false;
}
if ($proceed) {
$proceed = $this->_checkEqualSign($entry, $position);
}
while (!$proceed) {
$substring = substr($entry, 0, $position);
$position = strrpos($substring,'=');
$proceed = true;
if (substr($entry, $position-1, 1) == '\\') {
$proceed = false;
}
if ($proceed) {
$proceed = $this->_checkEqualSign($entry, $position);
}
}
$value = trim(substr($entry, $position+1));
$entry = substr($entry, 0, $position);
if (',' == substr($value, strlen($value)-1, 1)) {
$value = substr($value, 0, -1);
}
if ($this->_options['validate']) {
$this->_validateValue($value, $entrycopy);
}
if ($this->_options['stripDelimiter']) {
$value = $this->_stripDelimiter($value);
}
if ($this->_options['unwrap']) {
$value = $this->_unwrap($value);
}
if ($this->_options['removeCurlyBraces']) {
$value = $this->_removeCurlyBraces($value);
}
$position = strrpos($entry, ',');
$field = strtolower(trim(substr($entry, $position+1)));
$ret[$field] = $value;
$entry = substr($entry, 0, $position);
}
//Parsing cite and entry type
$arr = explode('{', $entry);
$ret['cite'] = trim($arr[1]);
$ret['entrytype'] = strtolower(trim($arr[0]));
if ('@' == $ret['entrytype']{0}) {
$ret['entrytype'] = substr($ret['entrytype'], 1);
}
if ($this->_options['validate']) {
if (!$this->_checkAllowedEntryType($ret['entrytype'])) {
$this->_generateWarning('WARNING_NOT_ALLOWED_ENTRY_TYPE', $ret['entrytype'], $entry.'}');
}
}
//Handling the authors
if (in_array('author', array_keys($ret)) && $this->_options['extractAuthors']) {
$ret['author'] = $this->_extractAuthors($ret['author']);
$ret['niceauthor'] = join(', ', array_map(function ($a) { return $a['nice']; }, $ret['author']));
$ret['sortauthor'] = join('', array_map(function ($a) { return $a['sort']; }, $ret['author']));
}
}
return $ret;
}
/**
* Checking whether the position of the '=' is correct
*
* Sometimes there is a problem if a '=' is used inside an entry (for example abstract).
* This method checks if the '=' is outside braces then the '=' is correct and true is returned.
* If the '=' is inside braces it contains to a equation and therefore false is returned.
*
* @access private
* @param string $entry The text of the whole remaining entry
* @param int the current used place of the '='
* @return bool true if the '=' is correct, false if it contains to an equation
*/
function _checkEqualSign($entry, $position)
{
$ret = true;
//This is getting tricky
//We check the string backwards until the position and count the closing an opening braces
//If we reach the position the amount of opening and closing braces should be equal
$length = strlen($entry);
$open = 0;
for ($i = $length-1; $i >= $position; $i--) {
$precedingchar = substr($entry, $i-1, 1);
$char = substr($entry, $i, 1);
if (('{' == $char) && ('\\' != $precedingchar)) {
$open++;
}
if (('}' == $char) && ('\\' != $precedingchar)) {
$open--;
}
}
if (0 != $open) {
$ret = false;
}
//There is still the posibility that the entry is delimited by double quotes.
//Then it is possible that the braces are equal even if the '=' is in an equation.
if ($ret) {
$entrycopy = trim($entry);
$lastchar = $entrycopy{strlen($entrycopy)-1};
if (',' == $lastchar) {
$lastchar = $entrycopy{strlen($entrycopy)-2};
}
if ('"' == $lastchar) {
//The return value is set to false
//If we find the closing " before the '=' it is set to true again.
//Remember we begin to search the entry backwards so the " has to show up twice - ending and beginning delimiter
$ret = false;
$found = 0;
for ($i = $length; $i >= $position; $i--) {
$precedingchar = substr($entry, $i-1, 1);
$char = substr($entry, $i, 1);
if (('"' == $char) && ('\\' != $precedingchar)) {
$found++;
}
if (2 == $found) {
$ret = true;
break;
}
}
}
}
return $ret;
}
/**
* Checking if the entry type is allowed
*
* @access private
* @param string $entry The entry to check
* @return bool true if allowed, false otherwise
*/
function _checkAllowedEntryType($entry)
{
return in_array($entry, $this->allowedEntryTypes);
}
/**
* Checking whether an at is outside an entry
*
* Sometimes an entry misses an entry brace. Then the at of the next entry seems to be
* inside an entry. This is checked here. When it is most likely that the at is an opening
* at of the next entry this method returns true.
*
* @access private
* @param string $entry The text of the entry until the at
* @return bool true if the at is correct, false if the at is likely to begin the next entry.
*/
function _checkAt($entry)
{
$ret = false;
$opening = array_keys($this->_delimiters);
$closing = array_values($this->_delimiters);
//Getting the value (at is only allowd in values)
if (strrpos($entry,'=') !== false) {
$position = strrpos($entry, '=');
$proceed = true;
if (substr($entry, $position-1, 1) == '\\') {
$proceed = false;
}
while (!$proceed) {
$substring = substr($entry, 0, $position);
$position = strrpos($substring,'=');
$proceed = true;
if (substr($entry, $position-1, 1) == '\\') {
$proceed = false;
}
}
$value = trim(substr($entry, $position+1));
$open = 0;
$char = '';
$lastchar = '';
for ($i = 0; $i < strlen($value); $i++) {
$char = substr($this->content, $i, 1);
if (in_array($char, $opening) && ('\\' != $lastchar)) {
$open++;
} elseif (in_array($char, $closing) && ('\\' != $lastchar)) {
$open--;
}
$lastchar = $char;
}
//if open is grater zero were are inside an entry
if ($open>0) {
$ret = true;
}
}
return $ret;
}
/**
* Stripping Delimiter
*
* @access private
* @param string $entry The entry where the Delimiter should be stripped from
* @return string Stripped entry
*/
function _stripDelimiter($entry)
{
$beginningdels = array_keys($this->_delimiters);
$length = strlen($entry);
$firstchar = substr($entry, 0, 1);
$lastchar = substr($entry, -1, 1);
while (in_array($firstchar, $beginningdels)) { //The first character is an opening delimiter
if ($lastchar == $this->_delimiters[$firstchar]) { //Matches to closing Delimiter
$entry = substr($entry, 1, -1);
} else {
break;
}
$firstchar = substr($entry, 0, 1);
$lastchar = substr($entry, -1, 1);
}
return $entry;
}
/**
* Unwrapping entry
*
* @access private
* @param string $entry The entry to unwrap
* @return string unwrapped entry
*/
function _unwrap($entry)
{
$entry = preg_replace('/\s+/', ' ', $entry);
return trim($entry);
}
/**
* Wordwrap an entry
*
* @access private
* @param string $entry The entry to wrap
* @return string wrapped entry
*/
function _wordwrap($entry)
{
if ( (''!=$entry) && (is_string($entry)) ) {
$entry = wordwrap($entry, $this->_options['wordWrapWidth'], $this->_options['wordWrapBreak'], $this->_options['wordWrapCut']);
}
return $entry;
}
/**
* Extracting the authors
*
* @access private
* @param string $entry The entry with the authors
* @return array the extracted authors
*/
function _extractAuthors($entry) {
$entry = $this->_unwrap($entry);
$authorarray = array();
$authorarray = explode(' and ', $entry);
for ($i = 0; $i < sizeof($authorarray); $i++) {
$author = trim($authorarray[$i]);
/*The first version of how an author could be written (First von Last)
has no commas in it*/
$first = '';
$von = '';
$last = '';
$jr = '';
if (strpos($author, ',') === false) {
$tmparray = array();
$tmparray = preg_split('/\s+/', $author);
$size = sizeof($tmparray);
if (1 == $size) { //There is only a last
$last = $tmparray[0];
} elseif (2 == $size) { //There is a first and a last
$first = $tmparray[0];
$last = $tmparray[1];
} else {
$invon = false;
$inlast = false;
for ($j=0; $j<($size-1); $j++) {
if ($inlast) {
$last .= ' '.$tmparray[$j];
} elseif ($invon) {
$case = $this->_determineCase($tmparray[$j]);
if (PEAR::isError($case)) {
// IGNORE?
} elseif ((0 == $case) || (-1 == $case)) { //Change from von to last
//You only change when there is no more lower case there
$islast = true;
for ($k=($j+1); $k<($size-1); $k++) {
$futurecase = $this->_determineCase($tmparray[$k]);
if (PEAR::isError($case)) {
// IGNORE?
} elseif (0 == $futurecase) {
$islast = false;
}
}
if ($islast) {
$inlast = true;
if (-1 == $case) { //Caseless belongs to the last
$last .= ' '.$tmparray[$j];
} else {
$von .= ' '.$tmparray[$j];
}
} else {
$von .= ' '.$tmparray[$j];
}
} else {
$von .= ' '.$tmparray[$j];
}
} else {
$case = $this->_determineCase($tmparray[$j]);
if (PEAR::isError($case)) {
// IGNORE?
} elseif (0 == $case) { //Change from first to von
$invon = true;
$von .= ' '.$tmparray[$j];
} else {
$first .= ' '.$tmparray[$j];
}
}
}
//The last entry is always the last!
$last .= ' '.$tmparray[$size-1];
}
} else { //Version 2 and 3
$tmparray = array();
$tmparray = explode(',', $author);
//The first entry must contain von and last
$vonlastarray = array();
$vonlastarray = explode(' ', $tmparray[0]);
$size = sizeof($vonlastarray);
if (1==$size) { //Only one entry->got to be the last
$last = $vonlastarray[0];
} else {
$inlast = false;
for ($j=0; $j<($size-1); $j++) {
if ($inlast) {
$last .= ' '.$vonlastarray[$j];
} else {
if (0 != ($this->_determineCase($vonlastarray[$j]))) { //Change from von to last
$islast = true;
for ($k=($j+1); $k<($size-1); $k++) {
$this->_determineCase($vonlastarray[$k]);
$case = $this->_determineCase($vonlastarray[$k]);
if (PEAR::isError($case)) {
// IGNORE?
} elseif (0 == $case) {
$islast = false;
}
}
if ($islast) {
$inlast = true;
$last .= ' '.$vonlastarray[$j];
} else {
$von .= ' '.$vonlastarray[$j];
}
} else {
$von .= ' '.$vonlastarray[$j];
}
}
}
$last .= ' '.$vonlastarray[$size-1];
}
//Now we check if it is version three (three entries in the array (two commas)
if (3==sizeof($tmparray)) {
$jr = $tmparray[1];
}
//Everything in the last entry is first
$first = $tmparray[sizeof($tmparray)-1];
}
$authorarray[$i] = array('first'=>trim($first), 'von'=>trim($von), 'last'=>trim($last), 'jr'=>trim($jr));
$authorarray[$i]['nice'] = join(' ', array_filter($authorarray[$i]));
$authorarray[$i]['sort'] = strtolower(trim($last).trim($first));
}
return $authorarray;
}
/**
* Case Determination according to the needs of BibTex
*
* To parse the Author(s) correctly a determination is needed
* to get the Case of a word. There are three possible values:
* - Upper Case (return value 1)
* - Lower Case (return value 0)
* - Caseless (return value -1)
*
* @access private
* @param string $word
* @return int The Case or PEAR_Error if there was a problem
*/
function _determineCase($word) {
$ret = -1;
$trimmedword = trim ($word);
/*We need this variable. Without the next of would not work
(trim changes the variable automatically to a string!)*/
if (is_string($word) && (strlen($trimmedword) > 0)) {
$i = 0;
$found = false;
$openbrace = 0;
while (!$found && ($i <= strlen($word))) {
$letter = substr($trimmedword, $i, 1);
$ord = ord($letter);
if ($ord == 123) { //Open brace
$openbrace++;
}
if ($ord == 125) { //Closing brace
$openbrace--;
}
if (($ord>=65) && ($ord<=90) && (0==$openbrace)) { //The first character is uppercase
$ret = 1;
$found = true;
} elseif ( ($ord>=97) && ($ord<=122) && (0==$openbrace) ) { //The first character is lowercase
$ret = 0;
$found = true;
} else { //Not yet found
$i++;
}
}
} else {
$ret = PEAR::raiseError('Could not determine case on word: '.(string)$word);
}
return $ret;
}
/**
* Validation of a value
*
* There may be several problems with the value of a field.
* These problems exist but do not break the parsing.
* If a problem is detected a warning is appended to the array warnings.
*
* @access private
* @param string $entry The entry aka one line which which should be validated
* @param string $wholeentry The whole BibTex Entry which the one line is part of
* @return void
*/
function _validateValue($entry, $wholeentry)
{
//There is no @ allowed if the entry is enclosed by braces
if (preg_match('/^{.*@.*}$/', $entry)) {
$this->_generateWarning('WARNING_AT_IN_BRACES', $entry, $wholeentry);
}
//No escaped " allowed if the entry is enclosed by double quotes
if (preg_match('/^\".*\\".*\"$/', $entry)) {
$this->_generateWarning('WARNING_ESCAPED_DOUBLE_QUOTE_INSIDE_DOUBLE_QUOTES', $entry, $wholeentry);
}
//Amount of Braces is not correct
$open = 0;
$lastchar = '';
$char = '';
for ($i = 0; $i < strlen($entry); $i++) {
$char = substr($entry, $i, 1);
if (('{' == $char) && ('\\' != $lastchar)) {
$open++;
}
if (('}' == $char) && ('\\' != $lastchar)) {
$open--;
}
$lastchar = $char;
}
if (0 != $open) {
$this->_generateWarning('WARNING_UNBALANCED_AMOUNT_OF_BRACES', $entry, $wholeentry);
}
}
/**
* Remove curly braces from entry
*
* @access private
* @param string $value The value in which curly braces to be removed
* @param string Value with removed curly braces
*/
function _removeCurlyBraces($value)
{
//First we save the delimiters
$beginningdels = array_keys($this->_delimiters);
$firstchar = substr($value, 0, 1);
$lastchar = substr($value, -1, 1);
$begin = '';
$end = '';
while (in_array($firstchar, $beginningdels)) { //The first character is an opening delimiter
if ($lastchar == $this->_delimiters[$firstchar]) { //Matches to closing Delimiter
$begin .= $firstchar;
$end .= $lastchar;
$value = substr($value, 1, -1);
} else {
break;
}
$firstchar = substr($value, 0, 1);
$lastchar = substr($value, -1, 1);
}
//Now we get rid of the curly braces
$value = preg_replace('/[\{\}]/', '', $value);
//Reattach delimiters
$value = $begin.$value.$end;
return $value;
}
/**
* Generates a warning
*
* @access private
* @param string $type The type of the warning
* @param string $entry The line of the entry where the warning occurred
* @param string $wholeentry OPTIONAL The whole entry where the warning occurred
*/
function _generateWarning($type, $entry, $wholeentry='')
{
$warning['warning'] = $type;
$warning['entry'] = $entry;
$warning['wholeentry'] = $wholeentry;
$this->warnings[] = $warning;
}
/**
* Cleares all warnings
*
* @access public
*/
function clearWarnings()
{
$this->warnings = array();
}
/**
* Is there a warning?
*
* @access public
* @return true if there is, false otherwise
*/
function hasWarning()
{
if (sizeof($this->warnings)>0) return true;
else return false;
}
/**
* Returns the amount of available BibTex entries
*
* @access public
* @return int The amount of available BibTex entries
*/
function amount()
{
return sizeof($this->data);
}
/**
* Returns the author formatted
*
* The Author is formatted as setted in the authorstring
*
* @access private
* @param array $array Author array
* @return string the formatted author string
*/
function _formatAuthor($array)
{
if (!array_key_exists('von', $array)) {
$array['von'] = '';
} else {
$array['von'] = trim($array['von']);
}
if (!array_key_exists('last', $array)) {
$array['last'] = '';
} else {
$array['last'] = trim($array['last']);
}
if (!array_key_exists('jr', $array)) {
$array['jr'] = '';
} else {
$array['jr'] = trim($array['jr']);
}
if (!array_key_exists('first', $array)) {
$array['first'] = '';
} else {
$array['first'] = trim($array['first']);
}
$ret = $this->authorstring;
$ret = str_replace("VON", $array['von'], $ret);
$ret = str_replace("LAST", $array['last'], $ret);
$ret = str_replace("JR", $array['jr'], $ret);
$ret = str_replace("FIRST", $array['first'], $ret);
return trim($ret);
}
/**
* Converts the stored BibTex entries to a BibTex String
*
* In the field list, the author is the last field.
*
* @access public
* @return string The BibTex string
*/
function bibTex()
{
$bibtex = '';
foreach ($this->data as $entry) {
//Intro
$bibtex .= '@'.strtolower($entry['entrytype']).' { '.$entry['cite'].",\n";
//Other fields except author
foreach ($entry as $key=>$val) {
if ($this->_options['wordWrapWidth']>0) {
$val = $this->_wordWrap($val);
}
if (!in_array($key, array('cite','entrytype','author'))) {
$bibtex .= "\t".$key.' = {'.$val."},\n";
}
}
//Author
if (array_key_exists('author', $entry)) {
if ($this->_options['extractAuthors']) {
$tmparray = array(); //In this array the authors are saved and the joind with an and
foreach ($entry['author'] as $authorentry) {
$tmparray[] = $this->_formatAuthor($authorentry);
}
$author = join(' and ', $tmparray);
} else {
$author = $entry['author'];
}
} else {
$author = '';
}
$bibtex .= "\tauthor = {".$author."}\n";
$bibtex.="}\n\n";
}
return $bibtex;
}
/**
* Adds a new BibTex entry to the data
*
* @access public
* @param array $newentry The new data to add
* @return void
*/
function addEntry($newentry)
{
$this->data[] = $newentry;
}
/**
* Returns statistic
*
* This functions returns a hash table. The keys are the different
* entry types and the values are the amount of these entries.
*
* @access public
* @return array Hash Table with the data
*/
function getStatistic()
{
$ret = array();
foreach ($this->data as $entry) {
if (array_key_exists($entry['entrytype'], $ret)) {
$ret[$entry['entrytype']]++;
} else {
$ret[$entry['entrytype']] = 1;
}
}
return $ret;
}
/**
* Returns the stored data in RTF format
*
* This method simply returns a RTF formatted string. This is done very
* simple and is not intended for heavy using and fine formatting. This
* should be done by BibTex! It is intended to give some kind of quick
* preview or to send someone a reference list as word/rtf format (even
* some people in the scientific field still use word). If you want to
* change the default format you have to override the class variable
* "rtfstring". This variable is used and the placeholders simply replaced.
* Lines with no data cause an warning!
*
* @return string the RTF Strings
*/
function rtf()
{
$ret = "{\\rtf\n";
foreach ($this->data as $entry) {
$line = $this->rtfstring;
$title = '';
$journal = '';
$year = '';
$authors = '';
if (array_key_exists('title', $entry)) {
$title = $this->_unwrap($entry['title']);
}
if (array_key_exists('journal', $entry)) {
$journal = $this->_unwrap($entry['journal']);
}
if (array_key_exists('year', $entry)) {
$year = $this->_unwrap($entry['year']);
}
if (array_key_exists('author', $entry)) {
if ($this->_options['extractAuthors']) {
$tmparray = array(); //In this array the authors are saved and the joind with an and
foreach ($entry['author'] as $authorentry) {
$tmparray[] = $this->_formatAuthor($authorentry);
}
$authors = join(', ', $tmparray);
} else {
$authors = $entry['author'];
}
}
if ((''!=$title) || (''!=$journal) || (''!=$year) || (''!=$authors)) {
$line = str_replace("TITLE", $title, $line);
$line = str_replace("JOURNAL", $journal, $line);
$line = str_replace("YEAR", $year, $line);
$line = str_replace("AUTHORS", $authors, $line);
$line .= "\n\\par\n";
$ret .= $line;
} else {
$this->_generateWarning('WARNING_LINE_WAS_NOT_CONVERTED', '', print_r($entry,1));
}
}
$ret .= '}';
return $ret;
}
/**
* Returns the stored data in HTML format
*
* This method simply returns a HTML formatted string. This is done very
* simple and is not intended for heavy using and fine formatting. This
* should be done by BibTex! It is intended to give some kind of quick
* preview. If you want to change the default format you have to override
* the class variable "htmlstring". This variable is used and the placeholders
* simply replaced.
* Lines with no data cause an warning!
*
* @return string the HTML Strings
*/
function html()
{
$ret = "\n";
foreach ($this->data as $entry) {
$line = $this->htmlstring;
$title = '';
$journal = '';
$year = '';
$authors = '';
if (array_key_exists('title', $entry)) {
$title = $this->_unwrap($entry['title']);
}
if (array_key_exists('journal', $entry)) {
$journal = $this->_unwrap($entry['journal']);
}
if (array_key_exists('year', $entry)) {
$year = $this->_unwrap($entry['year']);
}
if (array_key_exists('author', $entry)) {
if ($this->_options['extractAuthors']) {
$tmparray = array(); //In this array the authors are saved and the joind with an and
foreach ($entry['author'] as $authorentry) {
$tmparray[] = $this->_formatAuthor($authorentry);
}
$authors = join(', ', $tmparray);
} else {
$authors = $entry['author'];
}
}
if ((''!=$title) || (''!=$journal) || (''!=$year) || (''!=$authors)) {
$line = str_replace("TITLE", $title, $line);
$line = str_replace("JOURNAL", $journal, $line);
$line = str_replace("YEAR", $year, $line);
$line = str_replace("AUTHORS", $authors, $line);
$line .= "\n";
$ret .= $line;
} else {
$this->_generateWarning('WARNING_LINE_WAS_NOT_CONVERTED', '', print_r($entry,1));
}
}
$ret .= "
\n";
return $ret;
}
}
?>