/[drupal]/contributions/modules/biblio/biblio_theme.inc
ViewVC logotype

Contents of /contributions/modules/biblio/biblio_theme.inc

Parent Directory Parent Directory | Revision Log Revision Log | View Revision Graph Revision Graph


Revision 1.63 - (show annotations) (download) (as text)
Fri Oct 23 20:19:37 2009 UTC (4 weeks, 4 days ago) by rjerome
Branch: MAIN
CVS Tags: HEAD
Branch point for: DRUPAL-7--1
Changes since 1.62: +4 -3 lines
File MIME type: text/x-php
merged changes from DRUPAL-6--1 branch
1 <?php
2 // $Id: biblio_theme.inc,v 1.62 2009/10/01 01:45:42 rjerome Exp $
3 /**
4 *
5 * Copyright (C) 2006-2008 Ron Jerome
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 ****************************************************************************/
22 module_load_include('inc','biblio','biblio.pages');
23
24 /**
25 * @param $element
26 * @return unknown_type
27 */
28 function theme_biblio_coin_button($element) {
29 return '<a href="/biblio/regen_coins"><input type="button" name="'. $element['#name'] .'" value="'. $element['#value'] .'" /></a>';
30 }
31
32 /**
33 * @param $openURL
34 * @return unknown_type
35 */
36 function theme_biblio_openurl($openURL) {
37 $openurl_image = variable_get('biblio_openurlimage', '');
38 if ($openurl_image != '') {
39 $output .= '<div class="biblio-openurl-image"><a href="'. $openURL .'"target=_blank><img border="0" src="'. $openurl_image .'" /></a></div>';
40 }
41 else {
42 $output .= '<div class="biblio-openurl-text"><a href="'. $openURL .'" target=_blank>'. t('Find It Via OpenURL!') .'</a></div>';
43 }
44 return $output;
45 }
46
47 /**
48 * @param $node
49 * @return unknown_type
50 */
51 function biblio_openURL($node) {
52 global $user;
53 $openURL = '';
54 // Copyright: Matthias Steffens <mailto:refbase@extracts.de> and the file's
55 // original author.
56 // Original Author: Richard Karnesky <mailto:karnesky@gmail.com> //
57 // Adapted for biblio: Ron Jerome
58 // global $openURLResolver; // these variables are defined in 'ini.inc.php'
59 // global $hostInstitutionAbbrevName;
60 $openURLResolver = !empty($user->biblio_baseopenurl)?$user->biblio_baseopenurl:'';
61 if (empty($openURLResolver)) $openURLResolver = variable_get('biblio_baseopenurl', '');
62 if (!empty($openURLResolver)) {
63 $co = biblio_contextObject($node);
64
65 $sid = "biblio:". variable_get('site_name', 'Drupal');
66 $user_sid = !empty($user->biblio_openurl_sid)?$user->biblio_openurl_sid:'';
67 $co["sid"] = !empty($user_sid) ? $user_sid : variable_get('biblio_openurl_sid', $sid);
68
69 $openURL = $openURLResolver;
70 if (!ereg("\?", $openURLResolver))
71 $openURL .= "?";
72 else
73 $openURL .= "&amp;";
74 $openURL .= "ctx_ver=Z39.88-2004";
75 foreach ($co as $coKey => $coValue) {
76 $coKey = ereg_replace("rft.", "", $coKey);
77 $coKey = ereg_replace("au[0-9]*", "au", $coKey);
78 $openURL .= "&amp;". $coKey ."=". rawurlencode($coValue);
79 }
80 }
81 return $openURL;
82 }
83
84
85 /**
86 * DEPRECIATED! this was the original output format which is not to flexable it will be removed
87 * TODO: remove this function
88 * @param $node
89 * @param $base
90 * @param $style
91 * @return unknown_type
92 */
93 function theme_biblio_long($node, $base = 'biblio', $style = 'classic') {
94 if (module_exists('popups')){
95 popups_add_popups();
96 }
97 if (empty ($node->biblio_coins))
98 biblio_coins_generate($node);
99 $output .= filter_xss($node->biblio_coins, array('span'));
100 $layout = variable_get('biblio_node_layout', 'orig');
101 if (variable_get('biblio_node_layout', 'orig') == 'ft' && strlen(trim($node->body)) && user_access('view full text')) {
102 $output .= '<div class="biblio-head">'. theme('biblio_style', $node, $base, $style) .'</div>';
103 $annotation_field = variable_get('biblio_annotations', 'none');
104 if ($annotation_field != 'none' && $node-> $annotation_field) {
105 $output .= '<div class="biblio-annotation">';
106 $output .= check_markup($node->$annotation_field, $node->format, FALSE);
107 $output .= '</div>';
108 }
109 $output .= check_markup($node->body, $node->format, FALSE);
110 if (biblio_access('export', $node)) {
111 $output .= theme('biblio_export_links', $node);
112 }
113 return $output;
114 }
115 foreach ((array)$node->biblio_contributors[1] as $auth) {
116 $authors[] = theme('biblio_author_link', $auth['name'], $auth['cid'], $base);
117 }
118 $authors = implode('; ', (array)$authors);
119 $openurl_base = variable_get('biblio_baseopenurl', '');
120 if ($openurl_base)
121 $output .= theme('biblio_openurl', biblio_openurl($node, $openurl_base));
122 $output .= '<div class="biblio_type"><h3>'. t("Publication Type") .":</h3> $node->biblio_type_name</div>\n";
123 $output .= '<div class="biblio_authors"><h3>'. t("Authors") .':</h3> '. $authors ."</div>\n";
124 $output .= '<div class="biblio_source"><h3>'. t("Source") .': </h3> ';
125 $source = null;
126 if ($node->biblio_secondary_title)
127 $source .= check_plain($node->biblio_secondary_title);
128 if ($node->biblio_publisher) {
129 $source .= $source ? ", " : "";
130 $source .= check_plain($node->biblio_publisher);
131 }
132 if ($node->biblio_volume) {
133 $source .= $source ? ", " : "";
134 $source .= t('Volume') .' '. check_plain($node->biblio_volume);
135 }
136 if ($node->biblio_issue) {
137 $source .= $source ? ", " : "";
138 $source .= t('Issue') . ' '.check_plain($node->biblio_issue);
139 }
140 if ($node->biblio_number) {
141 $source .= $source ? ", " : "";
142 $source .= t('Number') . ' '.check_plain($node->biblio_number);
143 }
144 if ($node->biblio_place_published) {
145 $source .= $source ? ", " : "";
146 $source .= check_plain($node->biblio_place_published);
147 }
148 if ($node->biblio_pages) {
149 $source .= $source ? ", " : "";
150 $source .= 'p.'. check_plain($node->biblio_pages);
151 }
152 if (isset ($node->biblio_year)) {
153 $node->biblio_year = _biblio_text_year($node->biblio_year);
154 $source .= ' ('. check_plain($node->biblio_year) .')';
155 }
156 $output .= "$source</div>\n";
157 if ($node->biblio_isbn)
158 $output .= '<h3>'. t("ISBN") .':</h3> '. check_plain($node->biblio_isbn) ."\n";
159 if ($node->biblio_call_number)
160 $output .= '<h3>'. t("Call Number") .':</h3> '. check_plain($node->biblio_call_number) ."\n";
161 if ($node->biblio_accession_number)
162 $output .= '<h3>'. t("Accession Number") .':</h3> '. check_plain($node->biblio_accession_number) ."\n";
163 if ($node->biblio_other_number)
164 $output .= '<h3>'. t("Other Number") .':</h3> '. check_plain($node->biblio_other_number) ."\n";
165 if ($node->biblio_url) {
166 $attrib = (variable_get('biblio_links_target_new_window', null)) ? array(
167 'target' => '_blank'
168 ) : array();
169 $output .= '<h3>'. t("URL") .':</h3>'. l($node->biblio_url, $node->biblio_url, $attrib) ."\n";
170 }
171 if (!empty($node->biblio_keywords)) {
172 $output .= '<h3>'. t("Keywords") .':</h3> '. _biblio_keyword_links( $node->biblio_keywords, $base) ."\n";
173 }
174 if ($node->biblio_abst_e)
175 $output .= '<h3>'. t("Abstract") .':</h3> '. check_markup($node->biblio_abst_e, $node->format, FALSE) ."\n";
176 if ($node->biblio_abst_f)
177 $output .= '<p>'. check_markup($node->biblio_abst_f, $node->format, FALSE) ."\n";
178 if ($node->biblio_notes)
179 $output .= '<h3>'. t("Notes") .': </h3>'. check_markup($node->biblio_notes, $node->format, FALSE) ."\n";
180 if ( strlen(trim($node->body)) && user_access('view full text') ) {
181 $output .= '<h3>'.t('Full Text').':</h3>'.check_markup($node->body, $node->format, FALSE);
182 }
183
184 return $output;
185 }
186 /**
187 * @param $node
188 * @param $base
189 * @param $teaser
190 * @return unknown_type
191 */
192 function theme_biblio_tabular($node, $base = 'biblio', $teaser = false) {
193
194 if (module_exists('popups')){
195 popups_add_popups();
196 }
197 $tid = $node->biblio_type;
198 $style_name = biblio_get_style();
199 $style_function = "biblio_style_$style_name"."_author_options";
200 module_load_include('inc','biblio',"biblio_style_$style_name");
201 $fields = _biblio_get_field_information($node->biblio_type, TRUE);
202 $rows[] = array(
203 array('data' => t('Title'), 'class' => 'biblio-row-title'),
204 array('data' => filter_xss($node->title, biblio_get_allowed_tags()))
205 );
206 $rows[] = array(
207 array('data' => t('Publication Type'), 'class' => 'biblio-row-title'),
208 array('data' => $node->biblio_type_name)
209 );
210
211 if ($node->biblio_url) {
212 $attrib = (variable_get('biblio_links_target_new_window', null)) ? array('target' => '_blank') : array();
213 $node->biblio_url = l($node->biblio_url, $node->biblio_url, $attrib);
214 }
215 if ($node->biblio_doi) {
216 $doi_url = '';
217 $attrib = (variable_get('biblio_links_target_new_window', null)) ? array('target' => '_blank') : array();
218 if ( ($doi_start = strpos($node->biblio_doi, '10.')) !== FALSE) {
219 $doi = substr($node->biblio_doi, $doi_start);
220 $doi_url .= 'http://dx.doi.org/'. $doi;
221 }
222 $node->biblio_doi = l($node->biblio_doi, $doi_url, $attrib);
223 }
224
225 foreach ($fields as $key => $row) {
226 // handling the contributor categories like any other field orders them correctly by weight
227 if ($row['type'] == 'contrib_widget' && !empty($node->biblio_contributors[$row['fid']][0]['name']) ) {
228 $author_options = $style_function();
229 $author_options['numberOfAuthorsTriggeringEtAl'] = 100; //set really high so we see all authors
230 $data = theme('biblio_format_authors', $node->biblio_contributors[$row['fid']], $author_options, $inline);
231 }
232 else if (empty ($node->$row['name']) || $row['name'] == 'biblio_coins') continue;
233 else {
234 switch ($row['name']) {
235 case 'biblio_keywords' :
236 $data = _biblio_keyword_links($node->$row['name'], $base);
237 break;
238 case 'biblio_url' :
239 case 'biblio_doi' :
240 // check_plain is not need on these since they have gone through
241 // the l() function which does a check_plain
242 $data = $node-> $row['name'];
243 break;
244 default :
245 if ($row['type'] == 'textarea') {
246 $data = check_markup($node-> $row['name'], $node->format, FALSE);
247 }
248 else {
249 $data = check_plain($node-> $row['name']);
250 }
251 }
252 }
253 $rows[] = array(
254 array(
255 'data' => t($row['title']),
256 'class' => 'biblio-row-title'
257 ),
258 array(
259 'data' => $data
260 )
261 );
262 }
263
264
265 if (strlen(trim($node->body)) && user_access('view full text')) {
266 $rows[] = array(
267 array('data' => t('Full Text'), 'valign' => 'top'),
268 array('data' => check_markup($node->body, $node->format, FALSE))
269 );
270
271 }
272 $output = '<div id="biblio-node">';
273 $output .= filter_xss($node->biblio_coins, array('span'));
274 $header = array();
275 $output .= theme('table', $header, $rows);
276 $output .= '</div>';
277 return $output;
278 }
279
280 function theme_biblio_authors($contributors, $style = 'classic', $cat = 1, $inline = false, $glue = ', ') {
281 if (empty($contributors)) return; // t('No author information available');
282 $author_style_function = '_'.$style.'_format_author';
283 $author_links = variable_get('biblio_author_links', 1);
284 $base = variable_get('biblio_base', 'biblio');
285 foreach ($contributors as $key => $author) {
286 if (!empty($author['name']) && !isset($author['lastname'])) {
287 $author = biblio_parse_author($author, $cat); // this is needed for form preview to fill in all fields
288 }
289 if (strlen($author['name'])) {
290 $format = $author_style_function($author);
291 if ($author_links) $format = theme('biblio_author_link', $format, $author['cid'], $base, $inline);
292 // add the auth_type as css id to allow later formatting
293 $author_array[] = '<span id="'.$author['auth_type'].'">'.$format.'</span>';
294 }
295 }
296 if (empty($author_array)) return '';
297
298 $output = '<span class="biblio_authors">';
299 $output .= implode($glue, $author_array);
300 $output .= '</span>';
301 return $output;
302 }
303 function _biblio_get_latin1_regex() {
304 $alnum = "[:alnum:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß";
305
306 // Matches ISO-8859-1 letters:
307 $alpha = "[:alpha:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß";
308
309 // Matches ISO-8859-1 control characters:
310 $cntrl = "[:cntrl:]";
311
312 // Matches ISO-8859-1 dashes & hyphens:
313 $dash = "-–";
314
315 // Matches ISO-8859-1 digits:
316 $digit = "[\d]";
317
318 // Matches ISO-8859-1 printing characters (excluding space):
319 $graph = "[:graph:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß";
320
321 // Matches ISO-8859-1 lower case letters:
322 $lower = "[:lower:]äåáàâãçéèêëñöøóòôõüúùûíìîïæÿß";
323
324 // Matches ISO-8859-1 printing characters (including space):
325 $print = "[:print:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß";
326
327 // Matches ISO-8859-1 punctuation:
328 $punct = "[:punct:]";
329
330 // Matches ISO-8859-1 whitespace (separating characters with no visual representation):
331 $space = "[\s]";
332
333 // Matches ISO-8859-1 upper case letters:
334 $upper = "[:upper:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆ";
335
336 // Matches ISO-8859-1 "word" characters:
337 $word = "_[:alnum:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß";
338
339 // Defines the PCRE pattern modifier(s) to be used in conjunction with the above variables:
340 // More info: <http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php>
341 $patternModifiers = "";
342
343 return array($alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower,
344 $print, $punct, $space, $upper, $word, $patternModifiers);
345
346 }
347 /*
348 * Helper function for theme_biblio_format_authors() and theme_biblio_page_number()
349 */
350 function _biblio_get_utf8_regex() {
351
352 // Matches Unicode letters & digits:
353 $alnum = "\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}"; // Unicode-aware equivalent of "[:alnum:]"
354
355 // Matches Unicode letters:
356 $alpha = "\p{Ll}\p{Lu}\p{Lt}\p{Lo}"; // Unicode-aware equivalent of "[:alpha:]"
357
358 // Matches Unicode control codes & characters not in other categories:
359 $cntrl = "\p{C}"; // Unicode-aware equivalent of "[:cntrl:]"
360
361 // Matches Unicode dashes & hyphens:
362 $dash = "\p{Pd}";
363
364 // Matches Unicode digits:
365 $digit = "\p{Nd}"; // Unicode-aware equivalent of "[:digit:]"
366
367 // Matches Unicode printing characters (excluding space):
368 $graph = "^\p{C}\t\n\f\r\p{Z}"; // Unicode-aware equivalent of "[:graph:]"
369
370 // Matches Unicode lower case letters:
371 $lower = "\p{Ll}"; // Unicode-aware equivalent of "[:lower:]"
372
373 // Matches Unicode printing characters (including space):
374 $print = "\P{C}"; // same as "^\p{C}", Unicode-aware equivalent of "[:print:]"
375
376 // Matches Unicode punctuation (printing characters excluding letters & digits):
377 $punct = "\p{P}"; // Unicode-aware equivalent of "[:punct:]"
378
379 // Matches Unicode whitespace (separating characters with no visual representation):
380 $space = "\t\n\f\r\p{Z}"; // Unicode-aware equivalent of "[:space:]"
381
382 // Matches Unicode upper case letters:
383 $upper = "\p{Lu}\p{Lt}"; // Unicode-aware equivalent of "[:upper:]"
384
385 // Matches Unicode "word" characters:
386 $word = "_\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}"; // Unicode-aware equivalent of "[:word:]" (or "[:alnum:]" plus "_")
387
388 // Defines the PCRE pattern modifier(s) to be used in conjunction with the above variables:
389 // More info: <http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php>
390 $patternModifiers = "u"; // the "u" (PCRE_UTF8) pattern modifier causes PHP/PCRE to treat pattern strings as UTF-8
391
392 return array($alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower,
393 $print, $punct, $space, $upper, $word, $patternModifiers);
394 }
395
396 function _biblio_get_regex_patterns() {
397 // Checks if PCRE is compiled with UTF-8 and Unicode support
398 if (!@preg_match('/\pL/u', 'a')) {
399 // probably a broken PCRE library
400 return _biblio_get_latin1_regex();
401 } else {
402 // Unicode safe filter for the value
403 return _biblio_get_utf8_regex();
404 }
405 }
406 function theme_biblio_format_authors($contributors, $options, $inline = false)
407 {
408 if (empty($contributors)) return;
409 list($alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower,
410 $print, $punct, $space, $upper, $word, $patternModifiers) = _biblio_get_regex_patterns();
411 $base = variable_get('biblio_base', 'biblio');
412 $author_links = variable_get('biblio_author_links', 1);
413
414 $authorCount = count($contributors); // check how many authors we have to deal with
415 $output = ""; // this variable will hold the final author string
416 $includeStringAfterFirstAuthor = false;
417
418 if (empty($options['numberOfAuthorsTriggeringEtAl'])) $options['numberOfAuthorsTriggeringEtAl'] = $authorCount;
419
420 if (empty($options['includeNumberOfAuthors'])) $options['includeNumberOfAuthors'] = $authorCount;
421
422 foreach($contributors as $rank => $author)
423 {
424 if (empty($author['name'])) continue;
425 if (!isset($author['lastname'])) {
426 module_load_include('inc','biblio',"biblio.contributors");
427 $author = biblio_parse_author($author, $author['auth_type']); // this is needed for form preview to fill in all fields
428 }
429
430 if (!empty($author['firstname'])) {
431 if ($options['shortenGivenNames']) // if we're supposed to abbreviate given names
432 {
433 // within initials, reduce all full first names (-> defined by a starting uppercase character, followed by one ore more lowercase characters)
434 // to initials, i.e., only retain their first character
435 $author['firstname'] = preg_replace("/([$upper])[$lower]+/$patternModifiers", '\\1', $author['firstname']);
436 //$author['firstname'] = drupal_substr($author['firstname'], 0, 1);
437 // the next line caused extra betweenInitialsDelim to appear in some circumstances
438 //$author['firstname'] = preg_replace("/($space|$dash)?/$patternModifier", $options['betweenInitialsDelim'], $author['firstname']);
439 }
440 }
441 if (isset($author['initials'])) {
442 // within initials, remove any dots:
443 $author['initials'] = preg_replace("/([$upper])\.+/$patternModifiers", "\\1", $author['initials']);
444 //$author['initials'] = str_replace('.', '', $author['initials']);
445
446 // within initials, remove any spaces *between* initials:
447 $author['initials'] = preg_replace("/(?<=[-$upper]) +(?=[-$upper])/$patternModifiers", "", $author['initials']);
448 //$author['initials'] = str_replace(' ', '', $author['initials']);
449
450 // within initials, add a space after a hyphen, but only if ...
451 if (ereg(" $", $options['betweenInitialsDelim'])) // ... the delimiter that separates initials ends with a space
452 $author['initials'] = preg_replace("/-(?=[$upper])/$patternModifiers", "- ", $author['initials']);
453
454 // then, separate initials with the specified delimiter:
455 $delim = $options['betweenInitialsDelim'];
456 $author['initials'] = preg_replace("/([$upper])(?=[^$lower]+|$)/$patternModifiers", "\\1$delim", $author['initials']);
457
458 $shortenInitials = (isset($options['numberOfInitialsToKeep'])) ? $options['numberOfInitialsToKeep'] : FALSE;
459 if ($shortenInitials) $author['initials'] = drupal_substr($author['initials'], 0, $shortenInitials);
460
461 if ($options['shortenGivenNames'] && !empty($author['firstname'])) {
462 $author['firstname'] = $author['firstname'].$options['betweenInitialsDelim'].$author['initials'];
463 if ($shortenInitials) $author['firstname'] = drupal_substr($author['firstname'], 0, $shortenInitials);
464 }
465 elseif(!empty($author['firstname'])) {
466 $author['firstname'] = $author['firstname'].' '.$author['initials'];
467 }
468 elseif(empty($author['firstname'])) {
469 $author['firstname'] = $author['initials'];
470 }
471 }
472
473 // if there is a surname prefix like "van", "von" etc, stick it back before the last name.
474 if (!empty($author['prefix'])) $author['lastname'] = $author['prefix'] .' '. $author['lastname'];
475 if (!empty($author['suffix'])) $author['lastname'] = $author['lastname'] .', '. $author['suffix'];
476
477 if (!empty($author['firstname'])) {
478 if ($rank == 0) { // -> first author
479 if($options['initialsBeforeAuthorFirstAuthor']) {
480 $singleAuthorString = $author['firstname'].$options['AuthorsInitialsDelimFirstAuthor'].$author['lastname'];
481 }
482 else{
483 $singleAuthorString = $author['lastname'].$options['AuthorsInitialsDelimFirstAuthor'].$author['firstname'];
484 }
485 }
486 else { // $rank > 0 // -> all authors except the first one
487 if($options['initialsBeforeAuthorStandard']) {
488 $singleAuthorString = $author['firstname'].$options['AuthorsInitialsDelimStandard'].$author['lastname'];
489 }
490 else{
491 $singleAuthorString = $author['lastname'].$options['AuthorsInitialsDelimStandard'].$author['firstname'];
492 }
493 }
494 }
495 else {
496 $singleAuthorString = $author['lastname'];
497 }
498 if ($author_links) {
499 $singleAuthorString = theme('biblio_author_link',$singleAuthorString, $author['cid'], $base, $inline);
500 }
501 else {
502 $singleAuthorString = check_plain($singleAuthorString);
503 }
504 // append this author to the final author string:
505 if (($rank == 0) OR ($rank + 1) < $authorCount) // -> first author, or (for multiple authors) all authors except the last one
506 {
507 if ($rank == 0) // -> first author
508 $output .= $singleAuthorString;
509 else // -> for multiple authors, all authors except the first or the last one
510 $output .= $options['BetweenAuthorsDelimStandard'] . $singleAuthorString;
511
512 // we'll append the string in '$customStringAfterFirstAuthors' to the number of authors given in '$includeNumberOfAuthors' if the total number of authors is greater than the number given in '$numberOfAuthorsTriggeringEtAl':
513 if ((($rank + 1) == $options['includeNumberOfAuthors']) AND ($authorCount > $options['numberOfAuthorsTriggeringEtAl']))
514 {
515 if (ereg("__NUMBER_OF_AUTHORS__", $options['customStringAfterFirstAuthors']))
516 $customStringAfterFirstAuthors = preg_replace("/__NUMBER_OF_AUTHORS__/", ($authorCount - $options['includeNumberOfAuthors']), $options['customStringAfterFirstAuthors']); // resolve placeholder
517
518 $includeStringAfterFirstAuthor = true;
519 break;
520 }
521 }
522 elseif (($authorCount > 1) AND (($rank + 1) == $authorCount)) // -> last author (if multiple authors)
523 {
524 $output .= $options['BetweenAuthorsDelimLastAuthor'] . $singleAuthorString;
525 }
526 }
527
528 // do some final clean up:
529 if ($options['encodeHTML'])
530 //$output = encodeHTML($output); // HTML encode higher ASCII characters within the newly arranged author contents
531
532 if ($includeStringAfterFirstAuthor)
533 $output .= $options['customStringAfterFirstAuthors']; // the custom string won't get HTML encoded so that it's possible to include HTML tags (such as '<i>') within the string
534
535 $output = preg_replace("/ +/", " ", $output); // remove double spaces (which occur e.g., when both, $betweenInitialsDelim & $newAuthorsInitialsDelim..., end with a space)
536 $output = preg_replace("/ +([,.;:?!()]|$)/", "\\1", $output); // remove excess spaces before [,.;:?!()] and from the end of the author string
537
538 return $output;
539 }
540
541 function theme_biblio_author_link($author, $aid, $base='biblio', $inline = FALSE) {
542 $options = array();
543 $inline = $inline ? "/inline" : "";
544
545 if (isset($_GET['sort'])) {
546 $options['query'] .= "sort=" . $_GET['sort'];
547 }
548 if (isset($_GET['order'])) {
549 $options['query'] .= $options['query'] ? "&" : "" ;
550 $options['query'] .= "order=" . $_GET['order'];
551 }
552
553 $html = l(trim($author), "$base/author/$aid".$inline,$options );
554
555 return $html;
556 }
557
558 // Format page information:
559 //
560 // NOTES: - this function (and refbase in general) assumes following rules for the original formatting of page information in '$origPageInfo':
561 // - single-page items are given as a page range with identical start & end numbers (e.g. "127-127")
562 // - multi-page items are given as a page range where the end number is greater than the start number (e.g. "127-132")
563 // - for multi-page items where only the start page is known, a hyphen is appended to the start page (e.g. "127-")
564 // - total number of pages are given with a "pp" suffix (e.g. "498 pp"), see TODO
565 // - the given page info is left as is if it does not match any of the above rules (e.g. a single page number is ambiguous since it
566 // could mean a single page or the total number of pages)
567 // - the function attempts to deal with page locators that contain letters (e.g. "A1 - A3" or "4a-4c") but, ATM, locator parts (e.g. "A1")
568 // must contain at least one digit character & must not contain any whitespace
569 //
570 // TODO: - should we only use Unicode-aware regex expressions (i.e. always use '$space', '$digit' or '$word' instead of ' ', '\d' or '\w', etc)?
571 // - recognize & process total number of pages
572 // - for '$shortenPageRangeEnd=true', add support for page locators that contain letters (e.g. "A1 - A3" or "4a-4c")
573 function theme_biblio_page_number($origPageInfo, $pageRangeDelim = "-", $singlePagePrefix = "", $pageRangePrefix = "", $totalPagesPrefix = "", $singlePageSuffix = "", $pageRangeSuffix = "", $totalPagesSuffix = "", $shortenPageRangeEnd = false)
574 {
575 list($alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower,
576 $print, $punct, $space, $upper, $word, $patternModifiers) = _biblio_get_regex_patterns();
577
578 // Check original page info for any recognized page locators, and process them appropriately:
579 if (preg_match("/\w*\d+\w* *[$dash]+ *(?:\w*\d+\w*)?/$patternModifiers", $origPageInfo)) // the original page info contains a page range (like: "127-127", "127-132", "A1 - A3", "4a-4c", or "127-" if only start page given)
580 {
581 // Remove any whitespace around dashes or hyphens that indicate a page range:
582 $origPageInfo = preg_replace("/(\w*\d+\w*) *([$dash]+) *(\w*\d+\w*)?(?=[^\w\d]|$)/$patternModifiers", "\\1\\2\\3", $origPageInfo);
583
584 // Split original page info into its functional parts:
585 // NOTE: ATM, we simply split on any whitespace characters, then process all parts with page ranges
586 // (this will also reduce runs of whitespace to a single space)
587 $partsArray = preg_split("/ +/", $origPageInfo);
588 $partsCount = count($partsArray);
589
590 for ($i=0; $i < $partsCount; $i++)
591 {
592 // Format parts with page ranges:
593 // - single-page item:
594 if (preg_match("/(\w*\d+\w*)[$dash]+\\1(?=[^\w\d]|$)/$patternModifiers", $partsArray[$i])) // this part contains a page range with identical start & end numbers (like: "127-127")
595 $partsArray[$i] = preg_replace("/(\w*\d+\w*)[$dash]+\\1(?=[^\w\d]|$)/$patternModifiers", $singlePagePrefix . "\\1" . $singlePageSuffix, $partsArray[$i]);
596
597 // - multi-page item:
598 elseif (preg_match("/\w*\d+\w*[$dash]+(?:\w*\d+\w*)?(?=[^\w\d]|$)/$patternModifiers", $partsArray[$i])) // this part contains a page range (like: "127-132", or "127-" if only start page given)
599 {
600 // In case of '$shortenPageRangeEnd=true', we abbreviate ending page numbers so that digits aren't repeated unnecessarily:
601 if ($shortenPageRangeEnd AND preg_match("/\d+[$dash]+\d+/$patternModifiers", $partsArray[$i])) // ATM, only digit-only page locators (like: "127-132") are supported
602 {
603 // NOTE: the logic of this 'if' clause doesn't work if the original page info contains something like "173-190; 195-195" (where, for the first page range, '$endPage' would be "190;" and not "190")
604 list($startPage, $endPage) = preg_split("/[$dash]+/$patternModifiers", $partsArray[$i]);
605
606 $countStartPage = strlen($startPage);
607 $countEndPage = strlen($endPage);
608
609 if(($countStartPage == $countEndPage) AND ($startPage < $endPage))
610 {
611 for ($j=0; $j < $countStartPage; $j++)
612 {
613 if (preg_match("/^" . substr($startPage, $j, 1) . "/", $endPage)) // if the ending page number has a digit that's identical to the starting page number (at the same digit offset)
614 $endPage = substr($endPage, 1); // remove the first digit from the remaining ending page number
615 else
616 break;
617 }
618 }
619
620 $partsArray[$i] = $pageRangePrefix . $startPage . $pageRangeDelim . $endPage . $pageRangeSuffix;
621 }
622 else // don't abbreviate ending page numbers:
623 $partsArray[$i] = preg_replace("/(\w*\d+\w*)[$dash]+(\w*\d+\w*)?(?=[^\w\d]|$)/$patternModifiers", $pageRangePrefix . "\\1" . $pageRangeDelim . "\\2" . $pageRangeSuffix, $partsArray[$i]);
624 }
625 }
626
627 $newPageInfo = join(" ", $partsArray); // merge again all parts
628 }
629 else
630 $newPageInfo = $origPageInfo; // page info is ambiguous, so we don't mess with it
631
632 return $newPageInfo;
633 }
634
635
636 /**
637 * Applies a "style" function to a single node.
638 *
639 * @param $node A node
640 * @param $base The base url for biblio (defaults to /biblio)
641 * @param $style_name The name of the style to apply
642 * @param $inline "inline" mode returns the raw HTML rather than letting drupal render the whole page.
643 * @return A string containing the styled (HTML) node
644 */
645 function theme_biblio_style(& $node, $base = 'biblio', $style_name = 'classic', $inline = false) {
646 module_load_include('inc','biblio',"biblio_style_$style_name");
647
648 $style_function = "biblio_style_$style_name";
649 $styled_node = $style_function ($node, $base, $inline);
650 if (empty ($node->biblio_coins))
651 biblio_coins_generate($node);
652 return ($styled_node . filter_xss($node->biblio_coins, array('span')));
653 }
654
655 /**
656 * @param $node
657 * @param $base
658 * @param $style
659 * @param $inline
660 * @return unknown_type
661 */
662 function theme_biblio_entry($node, $base = 'biblio', $style = 'classic', $inline = false) {
663 $output = "\n".'<div class="biblio-entry">'."\n" ;
664
665 // first add the styled entry...
666 $output .= theme('biblio_style', $node, $base, $style, $inline);
667
668 // now add the various links
669 if ($node->biblio_abst_e) {
670 $output .= '<span class="biblio-abstract-link">';
671 $output .= l(" Abstract", "node/$node->nid") ."\n";
672 $output .= '</span>';
673 }
674 $annotation_field = variable_get('biblio_annotations', 'none');
675 if ($annotation_field != 'none' && $node-> $annotation_field) {
676 $output .= '<div class="biblio-annotation">';
677 $output .= check_markup($node->$annotation_field, $node->format, FALSE);
678 $output .= '</div>';
679 }
680 $openurl_base = variable_get('biblio_baseopenurl', '');
681
682 if ($openurl_base){
683 $output .= theme('biblio_openurl', biblio_openurl($node));
684 }
685
686 if (biblio_access('export', $node)) {
687 $base = variable_get('biblio_base', 'biblio');
688 $output .= theme('biblio_export_links',$node);
689 }
690
691 if (biblio_access('download', $node)) {
692 // add links to attached files (if any)
693 $output .= theme('biblio_download_links',$node);
694 }
695 $output .= "\n</div>";
696
697 return $output;
698 }
699
700 /**
701 * @param $form
702 * @return unknown_type
703 */
704 function theme_biblio_filters(& $form) {
705 if (sizeof($form['current'])) {
706 $output .= '<ul>';
707 foreach (element_children($form['current']) as $key) {
708 $output .= '<li>'. drupal_render($form['current'][$key]) .'</li>';
709 }
710 $output .= '</ul>';
711 }
712 $output .= '<dl class="multiselect">'. (sizeof($form['current']) ? '<dt><em>'. t('and') .'</em> '. t('where') .'</dt>' : '') .'<dd class="a">';
713 foreach (element_children($form['filter']) as $key) {
714 $output .= drupal_render($form['filter'][$key]);
715 }
716 $output .= '</dd>';
717 $output .= '<dt>'. t('is') .'</dt><dd class="b">';
718 foreach (element_children($form['status']) as $key) {
719 $output .= drupal_render($form['status'][$key]);
720 }
721 $output .= '</dd>';
722 $output .= '</dl>';
723 $output .= '<div class="container-inline" id="node-buttons">'. drupal_render($form['buttons']) .'</div>';
724 $output .= '<br class="clear" />';
725 return $output;
726 }
727
728 /**
729 * @param $form
730 * @return unknown_type
731 */
732 function theme_biblio_form_filter(& $form) {
733 $output .= '<div id="biblio-admin-filter">';
734 $output .= drupal_render($form['filters']);
735 $output .= '</div>';
736 $output .= drupal_render($form);
737 return $output;
738 }
739
740 /**
741 * @param $form
742 * @return unknown_type
743 */
744 function theme_biblio_admin_types_edit_form($form) {
745 drupal_add_tabledrag('field-table', 'order', 'sibling', 'weight',NULL,NULL,false);
746
747 $base = variable_get('biblio_base', 'biblio');
748 $tid = (!empty ($form['#parameters'][2])) ? $form['#parameters'][2] : FALSE;
749 // drupal_set_title($form['type_name'] ? $form['type_name']['#value'] : t('Common'));
750
751 // build the table with all the fields if no $tid is given, or only the common
752 // and customized fields if $tid is given
753 $conf_table = array();
754 foreach (element_children($form['configured_flds']) as $fld) {
755 $form['configured_flds'][$fld]['weight']['#attributes']['class'] = 'weight';
756
757 $conf_row = array();
758 $conf_row[] = array('data' => drupal_render($form['configured_flds'][$fld]['name']));
759 $conf_row[] = array('data' => drupal_render($form['configured_flds'][$fld]['title']));
760 if (isset($form['configured_flds'][$fld]['auth_type'])) {
761 $form['configured_flds'][$fld]['hint']['#size'] = 15;
762 $conf_row[] = array('data' => drupal_render($form['configured_flds'][$fld]['hint']));
763 $conf_row[] = array('data' => drupal_render($form['configured_flds'][$fld]['auth_type']));
764 } else {
765 $form['configured_flds'][$fld]['hint']['#size'] = ($tid ? 38: 36);
766 $conf_row[] = array('data' => drupal_render($form['configured_flds'][$fld]['hint']), 'colspan' => 2);
767 }
768 foreach (element_children($form['configured_flds'][$fld]['checkboxes']) as $oid) {
769 if (is_array($form['configured_flds'][$fld]['checkboxes'])) {
770 $conf_row[] = array(
771 'data' => drupal_render($form['configured_flds'][$fld]['checkboxes'][$oid]),
772 'title' => $oid);
773 }
774 }
775 $conf_row[] = array('data' => drupal_render($form['configured_flds'][$fld]['weight']));
776 $conf_table[] = array('data' => $conf_row, 'class' => 'draggable');
777 }
778 if ($tid) {
779 $header = array(t('Field Name'), t('Title'), t('Hint'), '', t('Visible'), t('Required'), t('Weight'));
780 }
781 else {
782 $header = array(t('Field Name'), t('Default Title'), t('Hint'), '', t('Common'), t('Required'), t('Autocomplete'), t('Weight'));
783 }
784 $output .= '<p>';
785 $output .= '<h2>'. drupal_render($form['top_message']) .'</h2>';
786 $output .= drupal_render($form['help']);
787 $output .= theme('table', $header, $conf_table, array('id' => 'field-table'));
788 $output .= '<p><center>'. drupal_render($form['submit']) .'</center></p>';
789 $output .= drupal_render($form);
790 return $output;
791 }
792
793 function theme_biblio_download_links($node = NULL) {
794 $files = '';
795 if (!empty ($node->files) && count($node->files) > 0 && user_access('view uploaded files')) {
796 $files .= '<span class="biblio_file_links">';
797 $files .= '&nbsp;'. t('Download') .':&nbsp;';
798 $file_count = 0;
799 foreach ($node->files as $file) {
800 if ($file->list) {
801 $file_count++;
802 $href = file_create_url($file->filepath);
803 $text = $file->description ? $file->description : $file->filename;
804 $files .= l($text, $href) .'&nbsp;('. format_size($file->filesize).')';
805 }
806 }
807 $files .= '</span>';
808 }
809 if (module_exists('filefield')) { // now lets get any CCK FileField files...
810 $fields = filefield_get_field_list('biblio');
811 foreach ($fields as $field_name => $field) {
812 if (filefield_view_access($field_name)) {
813 $field_files = filefield_get_node_files($node, $field_name);
814 if ($field_files) {
815 foreach ($field_files as $file) {
816 if ($file['fid']) {
817 $files .= theme('filefield_file', $file);
818 }
819 }
820 }
821 }
822 }
823 }
824
825 return $files;
826 }
827
828 /**
829 * Creates a group of links for the various export functions
830 * @param $nid the node id to export (if omitted, all nodes in the current view will be exported
831 * @return an un-ordered list of class "biblio-export-buttons"
832 */
833 function theme_biblio_export_links($node = NULL) {
834 global $pager_total_items;
835 $base = variable_get('biblio_base', 'biblio');
836 $show_link = variable_get('biblio_export_links', array('tagged' => TRUE, 'xml' => TRUE, 'bibtex' => TRUE));
837 $show_link['google'] = variable_get('biblio_google_link', 1);
838
839 $links = '';
840 if ($show_link['tagged']) $links .= '<li> '. _build_biblio_link($base, $node, 'tagged') .'</li>';
841 if ($show_link['xml']) $links .= '<li> '. _build_biblio_link($base, $node, 'xml') .'</li>';
842 if ($show_link['bibtex']) $links .= '<li> '. _build_biblio_link($base, $node, 'bibtex') .'</li>';
843 if ($show_link['google'] && !empty($node))
844 $links .= '<li> '. _build_biblio_link($base, $node, 'google') .'</li>';
845
846 if (!empty($links)) $links = '<ul class="biblio-export-buttons">' . $links . '</ul>';
847 if (empty($node) && !empty($links)) {
848 $links = t('Export @count results', array('@count' => $pager_total_items[0])).':' . $links;
849 }
850 return $links;
851 }
852
853 /**
854 * Creates a link to export a node (or view) in EndNote Tagged format
855 *
856 * @param $base this is the base url (defaults to /biblio)
857 * @param $nid the node id, if NULL then the current view is exported
858 * @return a link (<a href=...>Tagged</a>)
859 */
860 function _build_biblio_link($base, $node = NULL, $type = NULL) {
861 switch ($type) {
862 case 'bibtex':
863 $link = _build_biblio_bibtex_link($base, $node->nid);
864 break;
865 case 'tagged':
866 $link = _build_biblio_tagged_link($base, $node->nid);
867 break;
868 case 'xml':
869 $link = _build_biblio_xml_link($base, $node->nid);
870 break;
871 case 'google':
872 $link = _build_google_scholar_link($node);
873 break;
874 }
875 return l($link['title'], $link['href'], $link);
876 }
877
878 function _build_biblio_tagged_link($base, $nid) {
879 if (module_exists('popups') && !empty($nid)) {
880 $link = array('href' => "$base/export/tagged/$nid/popup", 'attributes' => array('class' => 'popups', 'title' => t("Click to get the EndNote Tagged output ")));
881 } else {
882 $link = array('href' => "$base/export/tagged/$nid", 'attributes' => array('title' => t("Click to download the EndNote Tagged formatted file")));
883 }
884 $link['title'] = t('Tagged');
885
886 return $link;
887 }
888 /**
889 * Creates a link to export a node (or view) in BibTEX format
890 *
891 * @param $base this is the base url (defaults to /biblio)
892 * @param $nid the node id, if NULL then the current view is exported
893 * @return a link (<a href=...>BibTEX</a>)
894 */
895 function _build_biblio_bibtex_link($base, $nid = NULL) {
896 if (module_exists('popups') && !empty($nid)) {
897 $link = array('href' => "$base/export/bibtex/$nid/popup", 'attributes' => array('class' => 'popups', 'title' => t("Click to get the BibTEX output ")));
898 } else {
899 $link = array('href' => "$base/export/bibtex/$nid", 'attributes' => array('title' => t("Click to download the BibTEX formatted file")));
900 }
901 $link['title'] = t('BibTex');
902
903 return $link;
904 }
905
906 /**
907 * Creates a link to export a node (or view) in XML format
908 *
909 * @param $base this is the base url (defaults to /biblio)
910 * @param $nid the node id, if NULL then the current view is exported
911 * @return a link (<a href=...>XML</a>)
912 */
913 function _build_biblio_xml_link($base, $nid = NULL) {
914 // if (module_exists('popups') && !empty($nid)) {
915 // $link = array('href' => "$base/export/xml/$nid/popup", 'attributes' => array('class' => 'popups', 'title' => t("Click to get the XML output ")));
916 // } else {
917 $link = array('href' => "$base/export/xml/$nid", 'attributes' => array('title' => t("Click to download the XML formatted file")));
918 // }
919 $link['title'] = t('XML');
920
921 return $link;
922 }
923 function _build_google_scholar_link($node) {
924 $link = 'http://scholar.google.com/scholar?as_q=';
925 $link .= '"'.str_replace(' ', '+', $node->title).'"';
926 $link .= '&btnG=Search+Scholar&as_epq=&as_oq=&as_eq=&as_occt=any&as_sauthors='.$node->biblio_contributors[1][0]['lastname'];
927
928 return array(
929 'title' => t('Google Scholar'),
930 'href' => $link,
931 'attributes' => array('title' => t("Click to search Google Scholar for this entry")),
932 );
933 }
934
935 /**
936 * @param $form
937 * @return unknown_type
938 */
939 function theme_biblio_contributors($form) {
940 $rows = array();
941 if ($form['#hideRole']) $headers = array('', t('Name'), t('Weight'));
942 else $headers = array('', t('Name'), t('Role'), t('Weight'));
943 drupal_add_tabledrag($form['#id'], 'order', 'sibling', 'rank');
944
945 foreach (element_children($form) as $key) {
946 // No need to print the field title every time.
947 unset ($form[$key]['name']['#title'], $form[$key]['auth_type']['#title']);
948 // Add class to group weight fields for drag and drop.
949 $form[$key]['rank']['#attributes']['class'] = 'rank';
950
951 // Build the table row.
952 $row = array('');
953 $row[] = array('data' => drupal_render($form[$key]['name']),
954 'class' => 'biblio-contributor');
955 if (!$form['#hideRole']) {
956 $row[] = array('data' => drupal_render($form[$key]['auth_type']),
957 'class' => 'biblio-contributor-type');
958 }
959 $row[] = drupal_render($form[$key]['rank']);
960 $rows[] = array('data' => $row, 'class' => 'draggable');
961 }
962 $output = theme('table', $headers, $rows, array('id' => $form['#id']));
963 $output .= drupal_render($form);
964 return $output;
965 }
966
967 /**
968 * This function creates a string of letters (A - Z), which
969 * depending on the sorting are either linked to author or title
970 * filters i.e. clicking on the A when in the listing is sorted by
971 * authors will bring up a list of all the entries where the first
972 * character of the primary authors last name is "A"
973 *
974 * @param $type either "author or title"
975 * @return a chunk of HTML code as described above
976 */
977 function theme_biblio_alpha_line($type = 'author',$current = NULL, $path = NULL) {
978 $options = array();
979 $base = variable_get('biblio_base', 'biblio');
980 $all = '';
981 switch ($type){
982 case 'authors':
983 case 'keywords':
984 $path = (ord(substr($_GET['q'],-1)) > 97) ? $_GET['q'] . "/" : substr($_GET['q'], 0, -1);
985 $all = '['.l(t('Show ALL'), substr($_GET['q'], 0, -2)).']' ;
986 break;
987 case 'author':
988 $options['query'] .= 'sort=author';
989 $path = "$base/ag/";
990 $all_query['query'] = 'sort=author'. ($_GET['order']?'&order='.$_GET['order']:'');
991 $all = '['.l(t('Show ALL'), $base,$all_query).']' ;
992 break;
993 case 'title':
994 $options['query'] .= 'sort=title';
995 $path = "$base/tg/";
996 $all_query['query'] = 'sort=title'. ($_GET