class PARSEENTRIES in Bibliography Module 7.2
Same name and namespace in other branches
- 5 bibtexParse/PARSEENTRIES.php \PARSEENTRIES
- 6.2 modules/bibtexParse/PARSEENTRIES.php \PARSEENTRIES
- 6 bibtexParse/PARSEENTRIES.php \PARSEENTRIES
- 7.3 plugins/biblio_style/bibtex/PARSEENTRIES.php \PARSEENTRIES
- 7 modules/bibtexParse/PARSEENTRIES.php \PARSEENTRIES
Hierarchy
- class \PARSEENTRIES
Expanded class hierarchy of PARSEENTRIES
2 string references to 'PARSEENTRIES'
- biblio_bibtex_biblio_import in modules/
bibtexParse/ biblio_bibtex.module - _biblio_bibtex_export in modules/
bibtexParse/ biblio_bibtex.module - Export data in bibtex format.
File
- modules/
bibtexParse/ PARSEENTRIES.php, line 134
View source
class PARSEENTRIES {
/**
* @return unknown_type
*/
function PARSEENTRIES() {
require_once drupal_get_path('module', 'biblio_bibtex') . '/transtab_latex_unicode.inc.php';
$this->transtab_latex_unicode = get_transtab_latex_unicode();
$this->preamble = $this->strings = $this->undefinedStrings = $this->entries = array();
$this->count = 0;
$this->fieldExtract = TRUE;
$this->removeDelimit = TRUE;
$this->expandMacro = FALSE;
$this->parseFile = TRUE;
$this->outsideEntry = TRUE;
$this->translate_latex = TRUE;
}
// Open bib file
/**
* @param $file
* @return none
*/
function openBib($file) {
if (!is_file($file)) {
die;
}
ini_set('auto_detect_line_endings', true);
$this->fid = fopen($file, 'r');
$this->parseFile = TRUE;
}
// Load a bibtex string to parse it
function loadBibtexString($bibtex_string) {
if (is_string($bibtex_string)) {
//$bibtex_string = $this->searchReplaceText($this->transtab_latex_unicode, $bibtex_string, FALSE);
$this->bibtexString = explode("\n", $bibtex_string);
}
else {
$this->bibtexString = $bibtex_string;
}
$this->parseFile = FALSE;
$this->currentLine = 0;
}
function searchReplaceText($searchReplaceActionsArray, $sourceString, $includesSearchPatternDelimiters = FALSE) {
$searchStrings = array_keys($searchReplaceActionsArray);
if (!$includesSearchPatternDelimiters) {
foreach ($searchStrings as $key => $value) {
$searchStrings[$key] = "/" . $value . "/";
// add search pattern delimiters
}
}
$replaceStrings = array_values($searchReplaceActionsArray);
// apply the search & replace actions defined in '$searchReplaceActionsArray' to the text passed in '$sourceString':
return preg_replace($searchStrings, $replaceStrings, $sourceString);
}
// Set strings macro
function loadStringMacro($macro_array) {
$this->userStrings = $macro_array;
}
// Close bib file
function closeBib() {
fclose($this->fid);
}
// Get a non-empty line from the bib file or from the bibtexString
function getLine() {
if ($this->parseFile) {
if (!feof($this->fid)) {
do {
$line = trim(fgets($this->fid));
} while (!feof($this->fid) && !$line);
return $line;
}
return FALSE;
}
else {
do {
$line = array_shift($this->bibtexString);
$line = trim($line);
$this->currentLine++;
} while ($this->bibtexString && !$line);
return $line;
}
}
// Extract value part of @string field enclosed by double-quotes or braces.
// The string may be expanded with previously-defined strings
function extractStringValue($string) {
// $string contains a end delimiter, remove it
$string = trim(substr($string, 0, strlen($string) - 1));
// remove delimiters and expand
$string = $this
->removeDelimitersAndExpand($string);
return $string;
}
// Extract a field
function fieldSplit($seg) {
// echo "**** ";print_r($seg);echo "<BR>";
// handle fields like another-field = {}
$array = preg_split("/,\\s*([-_.:,a-zA-Z0-9]+)\\s*={1}\\s*/U", $seg, PREG_SPLIT_DELIM_CAPTURE);
// echo "**** ";print_r($array);echo "<BR>";
//$array = preg_split("/,\s*(\w+)\s*={1}\s*/U", $seg, PREG_SPLIT_DELIM_CAPTURE);
if (!array_key_exists(1, $array)) {
return array(
$array[0],
FALSE,
);
}
return array(
$array[0],
$array[1],
);
}
// Extract and format fields
function reduceFields($oldString) {
// 03/05/2005 G. Gardey. Do not remove all occurences, juste one
// * correctly parse an entry ended by: somefield = {aValue}}
$lg = strlen($oldString);
if ($oldString[$lg - 1] == "}" || $oldString[$lg - 1] == ")" || $oldString[$lg - 1] == ",") {
$oldString = substr($oldString, 0, $lg - 1);
}
// $oldString = rtrim($oldString, "}),");
$split = preg_split("/=/", $oldString, 2);
$string = $split[1];
while ($string) {
list($entry, $string) = $this
->fieldSplit($string);
$values[] = $entry;
}
foreach ($values as $value) {
$pos = strpos($oldString, $value);
$oldString = substr_replace($oldString, '', $pos, strlen($value));
}
$rev = strrev(trim($oldString));
if ($rev[0] != ',') {
$oldString .= ',';
}
$keys = preg_split("/=,/", $oldString);
// 22/08/2004 - Mark Grimshaw
// I have absolutely no idea why this array_pop is required but it is. Seems to always be
// an empty key at the end after the split which causes problems if not removed.
array_pop($keys);
foreach ($keys as $key) {
$value = trim(array_shift($values));
$rev = strrev($value);
// remove any dangling ',' left on final field of entry
if ($rev[0] == ',') {
$value = rtrim($value, ",");
}
if (!$value) {
continue;
}
// 21/08/2004 G.Gardey -> expand macro
// Don't remove delimiters now needs to know if the value is a string macro
// $this->entries[$this->count][strtolower(trim($key))] = trim($this->removeDelimiters(trim($value)));
$key = strtolower(trim($key));
$value = trim($value);
$this->entries[$this->count][$key] = $value;
}
// echo "**** ";print_r($this->entries[$this->count]);echo "<BR>";
}
// Start splitting a bibtex entry into component fields.
// Store the entry type and citation.
function fullSplit($entry) {
$matches = preg_split("/@(.*)[{(](.*),/U", $entry, 2, PREG_SPLIT_DELIM_CAPTURE);
$this->entries[$this->count]['bibtexEntryType'] = strtolower(trim($matches[1]));
// sometimes a bibtex entry will have no citation key
if (preg_match("/=/", $matches[2])) {
// this is a field
$matches = preg_split("/@(.*)\\s*[{(](.*)/U", $entry, 2, PREG_SPLIT_DELIM_CAPTURE);
}
// print_r($matches); print "<P>";
$this->entries[$this->count]['bibtexCitation'] = $matches[2];
$this
->reduceFields($matches[3]);
}
// Grab a complete bibtex entry
function parseEntry($entry) {
set_time_limit(30);
// reset the script timer to avoid timeouts
$entry = $this->translate_latex ? $this
->searchReplaceText($this->transtab_latex_unicode, $entry, FALSE) : $entry;
$count = 0;
$lastLine = FALSE;
if (preg_match("/@(.*)([{(])/U", preg_quote($entry), $matches)) {
if (!array_key_exists(1, $matches)) {
return $lastLine;
}
if (preg_match("/string/i", trim($matches[1]))) {
$this->strings[] = $entry;
}
else {
if (preg_match("/preamble/i", trim($matches[1]))) {
$this->preamble[] = $entry;
}
else {
if (preg_match("/comment/i", $matches[1])) {
}
else {
if ($this->fieldExtract) {
$this
->fullSplit($entry);
}
else {
$this->entries[$this->count] = $entry;
}
$this->count++;
}
}
}
return $lastLine;
}
}
// Remove delimiters from a string
function removeDelimiters($string) {
if ($string && $string[0] == "\"") {
$string = substr($string, 1);
$string = substr($string, 0, -1);
}
else {
if ($string && $string[0] == "{") {
if (strlen($string) > 0 && $string[strlen($string) - 1] == "}") {
$string = substr($string, 1);
$string = substr($string, 0, -1);
}
}
else {
if (!is_numeric($string) && !array_key_exists($string, $this->strings) && array_search($string, $this->undefinedStrings) === FALSE) {
$this->undefinedStrings[] = $string;
// Undefined string that is not a year etc.
return '';
}
}
}
return $string;
}
// This function works like explode('#',$val) but has to take into account whether
// the character # is part of a string (i.e., is enclosed into "..." or {...} )
// or defines a string concatenation as in @string{ "x # x" # ss # {xx{x}x} }
function explodeString($val) {
$openquote = $bracelevel = $i = $j = 0;
while ($i < strlen($val)) {
if ($val[$i] == '"') {
$openquote = !$openquote;
}
elseif ($val[$i] == '{') {
$bracelevel++;
}
elseif ($val[$i] == '}') {
$bracelevel--;
}
elseif ($val[$i] == '#' && !$openquote && !$bracelevel) {
$strings[] = substr($val, $j, $i - $j);
$j = $i + 1;
}
$i++;
}
$strings[] = substr($val, $j);
return $strings;
}
// This function receives a string and a closing delimiter '}' or ')'
// and looks for the position of the closing delimiter taking into
// account the following Bibtex rules:
// * Inside the braces, there can arbitrarily nested pairs of braces,
// but braces must also be balanced inside quotes!
// * Inside quotes, to place the " character it is not sufficient
// to simply escape with \": Quotes must be placed inside braces.
function closingDelimiter($val, $delimitEnd) {
// echo "####>$delimitEnd $val<BR>";
$openquote = $bracelevel = $i = $j = 0;
while ($i < strlen($val)) {
// a '"' found at brace level 0 defines a value such as "ss{\"o}ss"
if ($val[$i] == '"' && !$bracelevel) {
$openquote = !$openquote;
}
elseif ($val[$i] == '{') {
$bracelevel++;
}
elseif ($val[$i] == '}') {
$bracelevel--;
}
if ($val[$i] == $delimitEnd && !$openquote && !$bracelevel) {
return $i;
}
$i++;
}
// echo "--> $bracelevel, $openquote";
return 0;
}
// Remove enclosures around entry field values. Additionally, expand macros if flag set.
function removeDelimitersAndExpand($string, $inpreamble = FALSE) {
// only expand the macro if flag set, if strings defined and not in preamble
if (!$this->expandMacro || empty($this->strings) || $inpreamble) {
$string = $this
->removeDelimiters($string);
}
else {
$stringlist = $this
->explodeString($string);
$string = "";
foreach ($stringlist as $str) {
// trim the string since usually # is enclosed by spaces
$str = trim($str);
// replace the string if macro is already defined
// strtolower is used since macros are case insensitive
if (isset($this->strings[strtolower($str)])) {
$string .= $this->strings[strtolower($str)];
}
else {
$string .= $this
->removeDelimiters(trim($str));
}
}
}
return $string;
}
// This function extract entries taking into account how comments are defined in BibTeX.
// BibTeX splits the file in two areas: inside an entry and outside an entry, the delimitation
// being indicated by the presence of a @ sign. When this character is met, BibTex expects to
// find an entry. Before that sign, and after an entry, everything is considered a comment!
function extractEntries() {
$inside = $possibleEntryStart = FALSE;
$entry = "";
while ($line = $this
->getLine()) {
if ($possibleEntryStart) {
$line = $possibleEntryStart . $line;
}
if (!$inside && strchr($line, "@")) {
// throw all characters before the '@'
$line = strstr($line, '@');
if (!strchr($line, "{") && !strchr($line, "(")) {
$possibleEntryStart = $line;
}
elseif (preg_match("/@.*([{(])/U", preg_quote($line), $matches)) {
$inside = TRUE;
if ($matches[1] == '{') {
$delimitEnd = '}';
}
else {
$delimitEnd = ')';
}
$possibleEntryStart = FALSE;
}
}
if ($inside) {
$entry .= " " . $line;
if ($j = $this
->closingDelimiter($entry, $delimitEnd)) {
// all characters after the delimiter are thrown but the remaining
// characters must be kept since they may start the next entry !!!
$lastLine = substr($entry, $j + 1);
$entry = substr($entry, 0, $j + 1);
// Strip excess whitespaces from the entry
$entry = preg_replace('/\\s\\s+/', ' ', $entry);
$this
->parseEntry($entry);
$entry = strchr($lastLine, "@");
if ($entry) {
$inside = TRUE;
}
else {
$inside = FALSE;
}
}
}
}
}
// Return arrays of entries etc. to the calling process.
function returnArrays() {
// global $transtab_latex_unicode; // defined in 'transtab_latex_unicode.inc.php'
foreach ($this->preamble as $value) {
preg_match("/.*?[{(](.*)/", $value, $matches);
$preamble = substr($matches[1], 0, -1);
$preambles['bibtexPreamble'] = trim($this
->removeDelimitersAndExpand(trim($preamble), TRUE));
}
if (isset($preambles)) {
$this->preamble = $preambles;
}
if ($this->fieldExtract) {
// Next lines must take into account strings defined by previously-defined strings
$strings = $this->strings;
// $this->strings is initialized with strings provided by user if they exists
// it is supposed that there are no substitutions to be made in the user strings, i.e., no #
$this->strings = isset($this->userStrings) ? $this->userStrings : array();
foreach ($strings as $value) {
// changed 21/08/2004 G. Gardey
// 23/08/2004 Mark G. account for comments on same line as @string - count delimiters in string value
$value = trim($value);
$matches = preg_split("/@\\s*string\\s*([{(])/i", $value, 2, PREG_SPLIT_DELIM_CAPTURE);
$delimit = $matches[1];
$matches = preg_split("/=/", $matches[2], 2, PREG_SPLIT_DELIM_CAPTURE);
// macros are case insensitive
$this->strings[strtolower(trim($matches[0]))] = $this
->extractStringValue($matches[1]);
}
}
// changed 21/08/2004 G. Gardey
// 22/08/2004 Mark Grimshaw - stopped useless looping.
// removeDelimit and expandMacro have NO effect if !$this->fieldExtract
if ($this->removeDelimit || $this->expandMacro && $this->fieldExtract) {
for ($i = 0; $i < count($this->entries); $i++) {
foreach ($this->entries[$i] as $key => $value) {
// 02/05/2005 G. Gardey don't expand macro for bibtexCitation
// and bibtexEntryType
if ($key != 'bibtexCitation' && $key != 'bibtexEntryType') {
$this->entries[$i][$key] = trim($this
->removeDelimitersAndExpand($this->entries[$i][$key]));
}
}
}
}
// EZ: Remove this to be able to use the same instance for parsing several files,
// e.g., parsing a entry file with its associated abbreviation file
// if (empty($this->preamble))
// $this->preamble = FALSE;
// if (empty($this->strings))
// $this->strings = FALSE;
// if (empty($this->entries))
// $this->entries = FALSE;
return array(
$this->preamble,
$this->strings,
$this->entries,
$this->undefinedStrings,
);
}
function &getEntries() {
if ($this->removeDelimit || $this->expandMacro && $this->fieldExtract) {
for ($i = 0; $i < count($this->entries); $i++) {
foreach ($this->entries[$i] as $key => $value) {
// 02/05/2005 G. Gardey don't expand macro for bibtexCitation
// and bibtexEntryType
if ($key != 'bibtexCitation' && $key != 'bibtexEntryType') {
$this->entries[$i][$key] = trim($this
->removeDelimitersAndExpand($this->entries[$i][$key]));
}
}
}
}
return $this->entries;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function | |||
PARSEENTRIES:: |
function |