biblio.contributors.inc in Bibliography Module 6.2
Same filename and directory in other branches
Functions related to contributors in Drupal biblio module.
File
includes/biblio.contributors.incView source
<?php
/**
* @file
* Functions related to contributors in Drupal biblio module.
*/
/**
* Retrieves a biblio contributor object by contributor ID.
*
* // @todo: What happens if array or non-existant ID integer passed?
* @param integer $cid
* Integer ID of a record in {biblio_contributor_data} table.
*
* @return object|?
* A contributor object if found; otherwise ??
*/
function biblio_get_contributor($cid) {
static $contributor = array();
if (!isset($contributor[$cid])) {
$contributor[$cid] = db_fetch_object(db_query('SELECT * FROM {biblio_contributor_data} WHERE cid = %d', $cid));
}
return $contributor[$cid];
}
/**
* Retrieves biblio contributor object based on exact match of contributor name.
*
* // @todo: What happens if array or non-existant name string passed?
*
* @param string $name
* Name of a contributor.
*
* @return object|?
* A contributor object if found; otherwise ??
*/
function biblio_get_contributor_by_name($name) {
return db_fetch_object(db_query("SELECT * FROM {biblio_contributor_data} bcd WHERE bcd.name = '%s'", array(
$name,
)));
}
/**
* Retrieves biblio contributor id based on exact match of contributor name.
*
* // @todo: What happens if array or non-existant name string passed?
*
* @param string $name
* Name of a contributor.
*
* @return int|null
* A contributor object if found; otherwise null
*/
function biblio_get_cid_by_name($name) {
static $contributor = array();
$cid = NULL;
if (!isset($contributor[$name])) {
$cid = db_result(db_query("SELECT cid FROM {biblio_contributor_data} bcd WHERE bcd.name = '%s'", array(
$name,
)));
if (!$cid) {
$cid = db_result(db_query("SELECT aka FROM {biblio_contributor_aka_data} bcad WHERE bcad.name = '%s'", array(
$name,
)));
}
if ($cid) {
$contributor[$name] = $cid;
}
}
return isset($contributor[$name]) ? $contributor[$name] : NULL;
}
/**
* Retrieves first biblio contributor object based on node revision ID.
*
* // @todo: What happens if array or non-existant ID passed?
*
* @param integer $vid
* A node revision ID.
*
* @return object|?
* A contributor object if found; otherwise ??
*/
function biblio_get_first_contributor($vid) {
static $contributor = array();
if (!isset($contributor[$vid])) {
$sql = "SELECT * " . "FROM {biblio_contributor} bc INNER JOIN {biblio_contributor_data} bcd ON bc.cid = bcd.cid " . "WHERE bc.vid = %d AND bc.rank = 0";
$contributor[$vid] = db_fetch_object(db_query($sql, $vid));
}
return $contributor[$vid];
}
/**
* Retrieves all biblio contributor objects associated with node revision ID.
*
* // @todo: What happens if array or non-existant ID passed?
*
* @param integer $vid
* A node revision ID.
*
* @return array
* A array of contributor objects if $vid found; otherwise empty array.
*/
function biblio_load_contributors($vid) {
$contributors = array();
// Do not change order of presentation of contributors.
$sql = "SELECT * " . "FROM {biblio_contributor} bc INNER JOIN {biblio_contributor_data} bcd ON bc.cid = bcd.cid " . "WHERE bc.vid = %d " . "ORDER BY bc.rank ASC";
$resource = db_query($sql, $vid);
while ($creator = db_fetch_array($resource)) {
$contributors[$creator['auth_category']][] = $creator;
}
return $contributors;
}
/**
* Adds additional author named "et al" to the end of the author array.
*
* @param $authors -
* Array of author arrays to possibly augment.
* @param integer $type
* Integer ID representing the author type.
*
* @return bool
* TRUE if author was added, FALSE if "et al" already present.
*/
function biblio_authors_add_etal(&$authors, $type) {
$etal = "et al";
$max_rank = 0;
foreach ($authors as $author) {
// et al author should be added only once per type
if ($author['auth_type'] != $type) {
continue;
}
if ($author['name'] == $etal) {
return FALSE;
}
$max_rank = max($max_rank, $author['rank']);
}
$authors[] = biblio_parse_author(array(
'name' => $etal,
'auth_type' => $type,
'lastname' => $etal,
'rank' => $max_rank + 1,
));
return true;
}
/**
* Parses array of contributors and augments with additional information.
*
* @param array $contributors
* Array of contibutor arrays
*
* @return array|null
* An array of enhanced author arrays.
*/
function biblio_parse_contributors($contributors) {
$result = array();
if (count($contributors) < 1) {
// @todo: Should something be returned here?
return;
}
foreach ($contributors as $category => $authors) {
$etal = array();
foreach ($authors as $author) {
// Remove any form of "et al" from name element for biblio_parse_author().
$author_cleaned = preg_replace("/et\\.?\\s+al\\.?/", '', $author['name']);
// If "et al" was present, store cleaned version for parsing.
if ($author_cleaned != $author['name']) {
$author['name'] = $author_cleaned;
// Mark this author as "to be added" in $etal array
$etal[$author['auth_type']] = TRUE;
}
$author['name'] = trim($author['name']);
if (strlen($author['name'])) {
$result[$category][] = biblio_parse_author($author, $category);
}
}
// Add "et al" authors for all neccessary contrbutor categories
foreach ($etal as $type => $dummy) {
// Add "et al" only if plain authors exists.
if (isset($result[$category])) {
biblio_authors_add_etal($result[$category], $type);
}
}
}
return $result;
}
/**
* Deletes all contributors associated with node ID.
*
* // @todo: Refactor to take a node ID or a node object?
* // @todo: Shouldn't this return success?
*
* @param object $node
* A node object that contains a property 'nid'.
*
* @return null
* ? change to $success?
*/
function biblio_delete_contributors($node) {
db_query('DELETE FROM {biblio_contributor} WHERE nid = %d', array(
':nid' => $node->nid,
));
return;
}
/**
* Deletes all contributors revisions associated with node revision ID.
*
* // @todo: Refactor to take a node revision ID or a node object?
*
* @param object $node
* A node object that contains a property 'vid'.
*
* @return integer
* Number of revisions deleted for supplied
*/
function biblio_delete_contributors_revision($node) {
db_query('DELETE FROM {biblio_contributor} WHERE vid = %d', array(
':vid' => $node->vid,
));
$count = db_affected_rows();
return $count;
}
/**
* Deletes a contributor based upon contributor ID.
*
* @param int $cid
* The ID of a contributor.
*
* @return integer
* The number of contributor records deleted for contributor ID.
*/
function biblio_delete_contributor($cid) {
$count = 0;
// @todo: Don't we want to delete x=ref data records first in case of failure
// in mid-process?
db_query('DELETE FROM {biblio_contributor}
WHERE cid = %d', array(
':cid' => $cid,
));
db_query('DELETE FROM {biblio_contributor_data}
WHERE cid = %d', array(
':cid' => $cid,
));
$count = db_affected_rows();
db_query('DELETE FROM {biblio_contributor_aka_data}
WHERE aka = %d', array(
':cid' => $cid,
));
return $count;
}
/**
*
*
* @param
*
*
* @return
*
*/
function biblio_delete_contributor_revision($cid, $vid) {
db_query('DELETE FROM {biblio_contributor}
WHERE cid = %d and vid = %d', array(
':cid' => $cid,
':vid' => $vid,
));
$count = db_affected_rows();
return $count;
}
/**
*
*
* @param
*
*
* @return
*
*/
function biblio_count_orphan_authors() {
return db_result(db_query('SELECT COUNT(*) FROM {biblio_contributor_data} bcd WHERE bcd.cid NOT IN (SELECT DISTINCT(bc.cid) FROM {biblio_contributor} bc )'));
}
/**
*
*
* @param
*
*
* @return
*
*/
function biblio_get_orphan_authors() {
$authors = array();
$result = db_query('SELECT distinct d.cid cid, name, affiliation
FROM {biblio_contributor_data} d
LEFT JOIN {biblio_contributor} c ON (d.cid=c.cid)
WHERE c.cid IS NULL');
while ($author = db_fetch_array($result)) {
$authors[] = $author;
}
return $authors;
}
/**
*
*
* @param
*
*
* @return
*
*/
function biblio_delete_orphan_authors($force = FALSE) {
if (variable_get('biblio_auto_orphaned_author_delete', 0) || $force) {
$active_cids = array();
$all_cids = array();
$result = db_query('SELECT cid FROM {biblio_contributor} GROUP BY cid');
while ($author = db_fetch_object($result)) {
$active_cids[] = $author->cid;
}
$result = db_query('SELECT cid FROM {biblio_contributor_data} GROUP BY cid');
while ($author = db_fetch_object($result)) {
$all_cids[] = $author->cid;
}
$orphans = array_diff($all_cids, $active_cids);
if (!empty($orphans)) {
db_query('DELETE FROM {biblio_contributor_data} WHERE cid IN (' . implode(',', $orphans) . ')');
$count = db_affected_rows();
$message = t('%count orphaned authors were deleted from the biblio_contributor_data table.', array(
'%count' => $count,
));
watchdog('biblio_cron', $message);
}
}
}
/**
*
*
* @param
*
*
* @return
*
*/
function biblio_insert_contributors($node) {
if (empty($node->biblio_contributors)) {
return true;
}
return _biblio_save_contributors($node->biblio_contributors, $node->nid, $node->vid);
}
/**
*
*
* @param
*
*
* @return
*
*/
function biblio_update_contributors($node) {
_biblio_save_contributors($node->biblio_contributors, $node->nid, $node->vid, TRUE);
return;
}
/**
*
*
* @param
*
*
* @return
*
*/
function biblio_save_contributor(&$author) {
return drupal_write_record('biblio_contributor_data', $author);
}
/**
*
*
* @param
*
*
* @return
*
*/
function biblio_update_contributor(&$author) {
if (!isset($author['cid'])) {
return false;
}
return drupal_write_record('biblio_contributor_data', $author, 'cid');
}
/**
*
*
* @param
*
*
* @return
*
*/
function _biblio_contributor_sort(&$authors) {
foreach ($authors as $key => $author) {
if (!isset($author['rank']) || empty($author['rank'])) {
$authors[$key]['rank'] = $key;
}
}
usort($authors, '_biblio_contributor_usort');
}
/**
*
*
* @param
*
*
* @return
*
*/
function _biblio_contributor_usort($a, $b) {
if (empty($a['name'])) {
return 1;
}
if (empty($b['name'])) {
return -1;
}
return $a['rank'] < $b['rank'] ? -1 : 1;
}
/**
* Save contributors to the database.
*
*
*
*
* @param $contributors
*
* @param $nid
*
* @param $vid
*
* @param $update
* (optional) A logical flag indicating whether ...
*
* @return success of database operations
*
*/
function _biblio_save_contributors(&$contributors, $nid, $vid, $update = FALSE) {
module_load_include('php', 'biblio', 'includes/Parser');
module_load_include('php', 'biblio', 'includes/Name');
$rank = 0;
db_query('DELETE FROM {biblio_contributor} WHERE nid = %d AND vid = %d', array(
$nid,
$vid,
));
$name_parser = new HumanNameParser_Parser();
if (is_array($contributors) && count($contributors)) {
foreach ($contributors as $cat => $authors) {
// Re-sort the authors by rank because the rank may have changed due to
// javascript tabledrag on the input form.
_biblio_contributor_sort($authors);
foreach ($authors as $key => $author) {
if (!empty($author['name'])) {
if (isset($author['cid']) && !empty($author['cid'])) {
// check to make sure the name wasn't changed
// this should only happen via the node/add/biblio input form
$auth = biblio_get_contributor($author['cid']);
if (!empty($auth) && isset($auth->name) && $auth->name != $author['name']) {
//if the name has changed, NULL the cid so a new entry is created
$author['cid'] = NULL;
}
else {
$contributors[$cat][$key] = array_merge($author, (array) $auth);
}
}
// if we don't have a cid, lets see if we can find and exact match
// to the name and use that cid
if (!isset($author['cid']) || empty($author['cid'])) {
$cid = biblio_get_cid_by_name($author['name']);
if ($cid) {
$author['cid'] = $cid;
$contributors[$cat][$key]['cid'] = $cid;
}
}
// if we still don't have a cid, then create a new entry in the biblio_contirbutor_data table
if (empty($author['cid'])) {
try {
$author = $name_parser
->parseName($author);
} catch (Exception $e) {
$link = l('in node ' . $nid, 'node/' . $nid);
$message = $e
->getMessage() . ' ' . $link;
drupal_set_message($message, 'error');
watchdog('biblio', $message, array(), WATCHDOG_ERROR);
}
$contributors[$cat][$key] = $author;
biblio_save_contributor($author);
}
// we should now have a cid, if not we are in big trouble...
if (empty($author['cid'])) {
//throw error that author was not saved
}
$link_array = array(
'nid' => $nid,
'vid' => $vid,
'cid' => $author['cid'],
'rank' => $rank++,
//((isset($author['rank']) && is_numeric($author['rank'])) ? $author['rank'] : $key),
'auth_type' => $author['auth_type'],
'auth_category' => $cat,
);
if (!drupal_write_record('biblio_contributor', $link_array)) {
return FALSE;
}
}
}
}
}
db_query("UPDATE {biblio_contributor_data} SET aka = cid WHERE aka = 0 OR aka IS NULL");
return TRUE;
}
/**
* Parses an author name into its component parts.
*
* This function is partly based on a collection of PHP classes to manipulate
* bibtex files and other work at http://bibliophile.sourceforge.net.
*
* That work was released through http://bibliophile.sourceforge.net under the
* GPL licence. Do whatever you like with this -- some credit to the author(s)
* would be appreciated. If you make improvements, please consider contacting
* the administrators at bibliophile.sourceforge.net so that your improvements
* can be added to the release package.
*
* Mark Grimshaw 2004/2005
* http://bibliophile.sourceforge.net
*
* 28/04/2005 - Mark Grimshaw.
* Efficiency improvements.
*
* 11/02/2006 - Daniel Reidsma.
* Changes to preg_matching to account for Latex characters in names such as
* {\"{o}}.
*
* @param string|array $contributor
* A string representing a name or an array with
* @param $category_id
* (optional)
*
* @return array|false
* FALSE if there was an error; otherwise, an associative array for the parsed
* parts of a name, including at minimum the keys:
* - name:
* - firstname:
* - initials:
* - lastname:
* - prefix:
* - md5:
*/
function biblio_parse_author($contributor, $category_id = 0) {
if (is_string($contributor)) {
$author_array = array();
$author_array['name'] = $contributor;
}
elseif (is_array($contributor) && isset($contributor['name'])) {
$author_array = $contributor;
}
else {
return FALSE;
}
if ($category_id == 5) {
$author_array['firstname'] = '';
$author_array['initials'] = '';
$author_array['lastname'] = trim($author_array['name']);
$author_array['prefix'] = '';
// @todo: set suffix to empty string?
}
else {
$value = trim($author_array['name']);
$appellation = $prefix = $surname = $firstname = $initials = '';
$prefix = "";
$value = preg_replace("/\\s{2,}/", ' ', $value);
// replace multiple white space by single space
$author = explode(",", $value);
$size = sizeof($author);
// If only one element to author array, no commas were found. Therefore,
// the name is something like Mark Grimshaw | Mark Nicholas Grimshaw |
// Mark N. Grimshaw | M N Grimshaw | or such.
if ($size == 1) {
// Is complete surname enclosed in {...}, unless the string starts with a backslash (\) because then it is
// probably a special latex-sign..
// 2006.02.11 DR: in the last case, any NESTED curly braces should also be taken into account! so second
// clause rules out things such as author="a{\"{o}}"
//
if (preg_match("/(.*){([^\\\\].*)}/", $value, $matches) && !preg_match("/(.*){\\\\.{.*}.*}/", $value, $dummy)) {
$author = explode(" ", $matches[1]);
$surname = $matches[2];
}
else {
$author = explode(" ", $value);
// Last of element of array is surname (no prefix if entered correctly).
$surname = array_pop($author);
}
}
elseif ($size == 2) {
// First element of array is surname (perhaps with a prefix).
list($surname, $prefix) = _biblio_extract_surname_parts(array_shift($author));
}
else {
// Middle element of array is 'Jr.', 'IV', etc.
$appellation = implode(' ', array_splice($author, 1, 1));
// First element of array is surname (perhaps with prefix).
list($surname, $prefix) = _biblio_extract_surname_parts(array_shift($author));
}
$remainder = implode(" ", $author);
list($firstname, $initials, $prefix2) = _biblio_extract_firstname_initials($remainder);
if (!empty($prefix2)) {
$prefix .= $prefix2;
}
$author_array['firstname'] = trim($firstname);
$author_array['initials'] = trim($initials);
$author_array['lastname'] = trim($surname);
$author_array['prefix'] = trim($prefix);
$author_array['suffix'] = trim($appellation);
}
$author_array['md5'] = biblio_calculate_contributor_hash($author_array);
return $author_array;
}
/**
* Creates an md5 hash string to ease contributor comparison logic.
*
* @param string|array $contributor
* A string with a name or array with one or more of the following elements,
* at least one of which is not empty:
* - firstname:
* - intiials:
* - prefix:
* - lastname:
*
* @return string
* An md5 hash string.
*/
function biblio_calculate_contributor_hash($contributor) {
$hash = '';
if (is_string($contributor)) {
$creator = biblio_parse_author(array(
'name' => trim($contributor),
));
}
elseif (is_array($contributor)) {
$creator = $contributor;
}
else {
return $hash;
}
$firstname = isset($creator['firstname']) ? $creator['firstname'] : '';
$initials = isset($creator['initials']) ? $creator['initials'] : '';
$prefix = isset($creator['prefix']) ? $creator['prefix'] : '';
$lastname = isset($creator['lastname']) ? $creator['lastname'] : '';
$string = $firstname . $initials . $prefix . $lastname;
$string = str_replace(' ', '', drupal_strtolower($string));
if (!empty($string)) {
$hash = md5($string);
}
return $hash;
}
/**
*
*
* grab firstname and initials which may be of form "A.B.C." or "A. B. C. " or " A B C " etc.
*
* @param $remainder
* The string representing the remainder of a name.
*
* @return array
* An array of three values: firstname, initials, prefix.
*/
function _biblio_extract_firstname_initials($remainder) {
$prefix = array();
$firstname = $initials = '';
$array = explode(" ", $remainder);
foreach ($array as $value) {
$firstChar = drupal_substr($value, 0, 1);
if (ord($firstChar) >= 97 && ord($firstChar) <= 122) {
$prefix[] = $value;
}
elseif (preg_match("/[a-zA-Z]{2,}/", trim($value))) {
$firstnameArray[] = trim($value);
}
else {
$initialsArray[] = trim(str_replace(".", " ", trim($value)));
}
}
if (isset($initialsArray)) {
$initials = implode(" ", $initialsArray);
}
if (isset($firstnameArray)) {
$firstname = implode(" ", $firstnameArray);
}
if (!empty($prefix)) {
$prefix = implode(" ", $prefix);
}
return array(
$firstname,
$initials,
$prefix,
);
}
/**
* Splits a surname string into its prefix and surname parts.
*
* A surname may have a title portion, such as 'den', 'von', 'de la', which are
* characterised by a lowercased first character. Any uppercased part means
* lowercased parts following are part of the surname (e.g. Van den Bussche).
*
* @param $input
* A string representing a name with a possible prefix.
*
* @return array
* An array with two elements representing surname and name prefix.
*/
function _biblio_extract_surname_parts($input) {
$noPrefix = FALSE;
$surname = FALSE;
$prefix = FALSE;
$surnameArray = explode(" ", $input);
foreach ($surnameArray as $value) {
$firstChar = substr($value, 0, 1);
if (!$noPrefix && ord($firstChar) >= 97 && ord($firstChar) <= 122) {
$prefix[] = $value;
}
else {
$surname[] = $value;
$noPrefix = TRUE;
}
}
if (!empty($surname)) {
$surname = implode(" ", $surname);
}
if (!empty($prefix)) {
$prefix = implode(" ", $prefix);
}
return array(
$surname,
$prefix,
);
}
/**
* Returns array of md5 hash strings for all biblio contributors.
*
* // @todo: Is this function presently used anywhere?
*
* @return array|null
* An array of md5 hash values; otherwise null if no contributors.
*/
function _biblio_load_contributor_hashes() {
static $md5 = array();
static $count = 0;
$db_count = db_result(db_query("SELECT COUNT(*) FROM {biblio_contributor_data}"));
if ($db_count != $count) {
$count = $db_count;
$md5 = array();
$result = db_query('SELECT md5,cid FROM {biblio_contributor_data}');
while ($row = db_fetch_array($result)) {
$md5[$row['cid']] = $row['md5'];
}
}
return count($md5) ? $md5 : NULL;
}
/**
* Retrieves a contributor ID value based on md5 hash value.
*
* // @todo: What is returned if no match found for md5 hash string?
*
* @param string $md5
* A md5 hash string.
*
* @return integer
* Integer ID of a contributor.
*/
function _biblio_get_cid_from_md5($md5) {
$cid = db_result(db_query("SELECT cid FROM {biblio_contributor_data} WHERE md5='%s'", $md5));
if (!$cid) {
$cid = db_result(db_query("SELECT aka FROM {biblio_contributor_aka_data} WHERE md5='%s'", $md5));
}
return $cid;
}
/**
*
*
* This function does what...
*
* @param object $user
* A user object with uid property.
* @param object $node
* A node object.
*
* @return true|null
* TRUE if the user ID matches the author Drupal user ID; otherwsie NULL.
*/
function biblio_contributor_user_access($user, $node) {
if (isset($node->biblio_contributors) && is_array($node->biblio_contributors)) {
foreach ($node->biblio_contributors as $cat => $authors) {
foreach ($authors as $key => $author) {
if ($author['drupal_uid'] == $user->uid) {
return TRUE;
}
}
}
}
return;
}
Functions
Name![]() |
Description |
---|---|
biblio_authors_add_etal | Adds additional author named "et al" to the end of the author array. |
biblio_calculate_contributor_hash | Creates an md5 hash string to ease contributor comparison logic. |
biblio_contributor_user_access | This function does what... |
biblio_count_orphan_authors | |
biblio_delete_contributor | Deletes a contributor based upon contributor ID. |
biblio_delete_contributors | Deletes all contributors associated with node ID. |
biblio_delete_contributors_revision | Deletes all contributors revisions associated with node revision ID. |
biblio_delete_contributor_revision | |
biblio_delete_orphan_authors | |
biblio_get_cid_by_name | Retrieves biblio contributor id based on exact match of contributor name. |
biblio_get_contributor | Retrieves a biblio contributor object by contributor ID. |
biblio_get_contributor_by_name | Retrieves biblio contributor object based on exact match of contributor name. |
biblio_get_first_contributor | Retrieves first biblio contributor object based on node revision ID. |
biblio_get_orphan_authors | |
biblio_insert_contributors | |
biblio_load_contributors | Retrieves all biblio contributor objects associated with node revision ID. |
biblio_parse_author | Parses an author name into its component parts. |
biblio_parse_contributors | Parses array of contributors and augments with additional information. |
biblio_save_contributor | |
biblio_update_contributor | |
biblio_update_contributors | |
_biblio_contributor_sort | |
_biblio_contributor_usort | |
_biblio_extract_firstname_initials | grab firstname and initials which may be of form "A.B.C." or "A. B. C. " or " A B C " etc. |
_biblio_extract_surname_parts | Splits a surname string into its prefix and surname parts. |
_biblio_get_cid_from_md5 | Retrieves a contributor ID value based on md5 hash value. |
_biblio_load_contributor_hashes | Returns array of md5 hash strings for all biblio contributors. |
_biblio_save_contributors | Save contributors to the database. |