CiteProc - PHP
A PHP implementation of the CSL citation processor "CiteProc"

CiteProc.php

Go to the documentation of this file.
00001 <?php
00002 // $Id: _cite_proc_8php_source.html,v 1.2 2012-12-13 16:04:54 sbo Exp $
00023 class citeproc {
00024   public    $bibliography;
00025   public    $citation;
00026   public    $style;
00027   protected $macros;
00028   private   $info;
00029   protected $locale;
00030   protected $style_locale;
00031   private   $mapper = NULL;
00032 
00033   function __construct($csl = NULL, $lang = 'en') {
00034     if ($csl) {
00035       $this->init($csl, $lang);
00036     }
00037   }
00038 
00039   function init($csl, $lang) {
00040     // define field values appropriate to your data in the csl_mapper class and un-comment the next line.
00041     //$this->mapper = new csl_mapper();
00042 
00043     $csl_doc = new DOMDocument();
00044 
00045     if ($csl_doc->loadXML($csl)) {
00046 
00047       $style_nodes = $csl_doc->getElementsByTagName('style');
00048       if ($style_nodes) {
00049         foreach ($style_nodes as $style) {
00050           $this->style = new csl_style($style);
00051         }
00052       }
00053 
00054       $info_nodes = $csl_doc->getElementsByTagName('info');
00055       if ($info_nodes) {
00056         foreach ($info_nodes as $info) {
00057           $this->info = new csl_info($info);
00058         }
00059       }
00060 
00061       $this->locale = new csl_locale($lang);
00062       $this->locale->set_style_locale($csl_doc);
00063 
00064 
00065       $macro_nodes = $csl_doc->getElementsByTagName('macro');
00066       if ($macro_nodes) {
00067         $this->macros = new csl_macros($macro_nodes, $this);
00068       }
00069 
00070       $citation_nodes = $csl_doc->getElementsByTagName('citation');
00071       foreach ($citation_nodes as $citation) {
00072         $this->citation = new csl_citation($citation, $this);
00073       }
00074 
00075       $bibliography_nodes = $csl_doc->getElementsByTagName('bibliography');
00076       foreach ($bibliography_nodes as $bibliography) {
00077         $this->bibliography = new csl_bibliography($bibliography, $this);
00078       }
00079     }
00080   }
00081   function render($data) {
00082     $text = '';
00083   //  $text .=  (isset($this->citation))? $this->citation->render($data) : '';
00084     $text .=  (isset($this->bibliography))? $this->bibliography->render($data) : '';
00085     return $text;
00086   }
00087 
00088   function render_macro($name, $data, $mode) {
00089     return $this->macros->render_macro($name, $data, $mode);
00090   }
00091 
00092   function get_locale($type, $arg1, $arg2 = NULL, $arg3 = NULL) {
00093     return $this->locale->get_locale($type, $arg1, $arg2, $arg3);
00094   }
00095 
00096   function map_field($field) {
00097     if ($this->mapper) {
00098       return $this->mapper->map_field($field);
00099     }
00100     return ($field);
00101   }
00102   function map_type($field) {
00103     if ($this->mapper) {
00104       return $this->mapper->map_type($field);
00105     }
00106     return ($field);
00107   }
00108 }
00109 
00110 class csl_factory {
00111   public static function create($dom_node, $citeproc = NULL) {
00112     $class_name =  'csl_' . str_replace('-', '_', $dom_node->nodeName);
00113     if (class_exists($class_name)) {
00114       return new $class_name($dom_node, $citeproc);
00115     }
00116     else {
00117       return NULL;
00118     }
00119   }
00120 }
00121 
00122 class csl_collection {
00123   protected  $elements = array();
00124 
00125   function add_element($elem) {
00126     $this->elements[] = $elem;
00127   }
00128 
00129   function render($data, $mode) {}
00130 
00131   function format($text) {return $text;}
00132 
00133 }
00134 
00135 class csl_element extends csl_collection {
00136   protected $attributes = array();
00137   protected $citeproc;
00138 
00139   function __construct($dom_node = NULL, $citeproc = NULL) {
00140 
00141     $this->citeproc   = &$citeproc;
00142     $this->attributes = $this->set_attributes($dom_node);
00143     $this->init($dom_node, $citeproc);
00144 
00145   }
00146 
00147   function init($dom_node, $citeproc) {
00148     if (!$dom_node) return;
00149 
00150     foreach ($dom_node->childNodes as $node) {
00151       if ($node->nodeType == 1) {
00152         $this->add_element(csl_factory::create($node, $citeproc));
00153       }
00154     }
00155   }
00156 
00157   function set_attribute($name, $value) {
00158     $this->attributes[$name] = $value;
00159   }
00160 
00161   function set_attributes($dom_node) {
00162     $att = array();
00163     $element_name = $dom_node->nodeName;
00164     if (isset($dom_node->attributes->length)) {
00165       for ($i=0; $i < $dom_node->attributes->length; $i++) {
00166         $value = $dom_node->attributes->item($i)->value;
00167         $name  = str_replace(' ', '_', $dom_node->attributes->item($i)->name);
00168         if ($name == 'type' ) {
00169           $value = $this->citeproc->map_type($value);
00170         }
00171 
00172         if (($name == 'variable'  || $name == 'is-numeric') && $element_name != 'label') {
00173           $value = $this->citeproc->map_field($value);
00174         }
00175         $att[$name]  = $value;
00176       }
00177     }
00178     return $att;
00179   }
00180 
00181   function get_attributes($name = NULL) {
00182     if ($name) {
00183       return (isset($this->attributes[$name])) ? $this->attributes[$name] : NULL;
00184     }
00185     else {
00186       return $this->attributes;
00187     }
00188   }
00189 
00190   function get_hier_attributes() {
00191     $hier_attr = array();
00192     $hier_names = array('and', 'delimiter-precedes-last', 'et-al-min', 'et-al-use-first',
00193                         'et-al-subsequent-min', 'et-al-subsequent-use-first', 'initialize-with',
00194                         'name-as-sort-order', 'sort-separator', 'name-form', 'name-delimiter',
00195                         'names-delimiter');
00196     foreach ($hier_names as $name) {
00197       if (isset($this->attributes[$name])) {
00198         $hier_attr[$name] = $this->attributes[$name];
00199       }
00200     }
00201     return $hier_attr;
00202   }
00203 
00204   function name($name = NULL) {
00205     if ($name) {
00206       $this->attributes['name'] = $name;
00207     }
00208     else {
00209       return str_replace(' ', '_', $this->attributes['name']);
00210     }
00211   }
00212 
00213 }
00214 
00215 class csl_rendering_element extends csl_element {
00216 
00217   function render($data, $mode = NULL) {
00218     $text = '';
00219     $text_parts = array();
00220 
00221     $delim = $this->get_attributes('delimiter');
00222     foreach ($this->elements as $element) {
00223       $text_parts[] = $element->render($data, $mode);
00224     }
00225     $text = implode($delim, $text_parts); // insert the delimiter if supplied.
00226 
00227     return $this->format($text);
00228   }
00229 
00230 }
00231 
00232 class csl_format extends csl_rendering_element {
00233   protected $no_op;
00234   protected $format;
00235 
00236   function __construct($dom_node = NULL, $citeproc = NULL) {
00237     parent::__construct($dom_node, $citeproc);
00238     $this->init_formatting();
00239   }
00240 
00241   function init_formatting() {
00242     $this->no_op = TRUE;
00243     $this->format  = '';
00244     if (isset($this->attributes['quotes'])) {
00245       $this->attributes['quotes'] = array();
00246       $this->attributes['quotes']['punctuation-in-quote'] = $this->citeproc->get_locale('style_option', 'punctuation-in-quote');
00247       $this->attributes['quotes']['open-quote'] = $this->citeproc->get_locale('term', 'open-quote');
00248       $this->attributes['quotes']['close-quote'] = $this->citeproc->get_locale('term', 'close-quote');
00249       $this->attributes['quotes']['open-inner-quote'] = $this->citeproc->get_locale('term', 'open-inner-quote');
00250       $this->attributes['quotes']['close-inner-quote'] = $this->citeproc->get_locale('term', 'close-inner-quote');
00251       $this->no_op = FALSE;
00252     }
00253     if (isset($this->attributes['prefix'])) $this->no_op = FALSE;
00254     if (isset($this->attributes['suffix'])) $this->no_op = FALSE;
00255     if (isset($this->attributes['display'])) $this->no_op = FALSE;
00256 
00257     $this->format .= (isset($this->attributes['font-style']))      ? 'font-style: ' . $this->attributes['font-style'] . ';' : '';
00258     $this->format .= (isset($this->attributes['font-family']))     ? 'font-family: ' . $this->attributes['font-family'] . ';' : '';
00259     $this->format .= (isset($this->attributes['font-weight']))     ? 'font-weight: ' . $this->attributes['font-weight'] . ';' : '';
00260     $this->format .= (isset($this->attributes['font-variant']))    ? 'font-variant: ' . $this->attributes['font-variant'] . ';' : '';
00261     $this->format .= (isset($this->attributes['text-decoration'])) ? 'text-decoration: ' . $this->attributes['text-decoration'] . ';' : '';
00262     $this->format .= (isset($this->attributes['vertical-align']))  ? 'vertical-align: ' . $this->attributes['vertical-align'] . ';' : '';
00263     // $this->format .= (isset($this->attributes['display'])  && $this->attributes['display']  == 'indent')  ? 'padding-left: 25px;' : '';
00264 
00265     if (isset($this->attributes['text-case']) || !empty($this->format)) $this->no_op = FALSE;
00266 
00267   }
00268 
00269   function format($text) {
00270 
00271     if (empty($text) || $this->no_op) return $text;
00272     if (isset($this->attributes['text-case'])) {
00273       switch ($this->attributes['text-case']) {
00274         case 'uppercase':
00275           $text = mb_strtoupper($text);
00276           break;
00277         case 'lowercase':
00278           $text = mb_strtolower($text);
00279           break;
00280         case 'capitalize-all':
00281         case 'title':
00282           $text = mb_convert_case($text, MB_CASE_TITLE);
00283           break;
00284         case 'capitalize-first':
00285           $text[0] = mb_strtoupper($text[0]);
00286           break;
00287       }
00288     }
00289     $open_quote = (isset($this->attributes['quotes']['open-quote'])) ? $this->attributes['quotes']['open-quote'] : '';
00290     $close_quote = (isset($this->attributes['quotes']['close-quote'])) ? $this->attributes['quotes']['close-quote'] : '';
00291     $prefix = (isset($this->attributes['prefix'])) ? $this->attributes['prefix'] . $open_quote : '' . $open_quote;
00292     $suffix = (isset($this->attributes['suffix'])) ? $this->attributes['suffix'] : '';
00293     if ($close_quote && !empty($suffix) && $this->attributes['quotes']['punctuation-in-quote']) {
00294       if (strpos($suffix, '.') !== FALSE || strpos($suffix, ',') !== FALSE) {
00295         $suffix =  $suffix . $close_quote;
00296       }
00297     }
00298     elseif ($close_quote) {
00299       $suffix =  $close_quote . $suffix;
00300     }
00301     elseif (!empty($suffix)) {
00302       if ($text[(strlen($text)-1)] == $suffix[0]) $text = substr($text, 0, -1);
00303     }
00304 
00305     if (!empty($this->format)) {
00306       $text = '<span style="' . $this->format . '">' . $text . '</span>';
00307     }
00308     if (isset($this->attributes['display'])  && $this->attributes['display']  == 'indent') {
00309       return '<div style="text-indent: 0px; padding-left: 45px;">' . $prefix . $text . $suffix . '</div>';
00310     }
00311 
00312     return $prefix . $text . $suffix;
00313   }
00314 
00315 }
00316 
00317 class csl_info {
00318   public $title;
00319   public $id;
00320   public $authors = array();
00321   public $links = array();
00322 
00323   function __construct($dom_node) {
00324     $name = array();
00325     foreach ($dom_node->childNodes as $node) {
00326       if ($node->nodeType == 1) {
00327         switch ($node->nodeName) {
00328           case 'author':
00329           case 'contributor':
00330             foreach ($node->childNodes as $authnode) {
00331               if ($node->nodeType == 1)
00332                 $name[$authnode->nodeName] = $authnode->nodeValue;
00333             }
00334             $this->authors[] = $name;
00335             break;
00336           case 'link':
00337             foreach ($node->attributes as $attribute) {
00338               $this->links[] = $attribute->value;
00339             }
00340             break;
00341           default:
00342             $this->{$node->nodeName} = $node->nodeValue;
00343         }
00344       }
00345     }
00346 
00347   }
00348 }
00349 
00350 class csl_terms {
00351 
00352 }
00353 
00354 class csl_name extends csl_format {
00355   private $name_parts = array();
00356   private $attr_init = FALSE;
00357 
00358   function __construct($dom_node, $citeproc = NULL) {
00359 
00360     $tags = $dom_node->getElementsByTagName('name-part');
00361     if ($tags) {
00362       foreach ($tags as $tag) {
00363         $name_part = $tag->getAttribute('name');
00364         $tag->removeAttribute('name');
00365         for ($i=0; $i < $tag->attributes->length; $i++) {
00366           $value = $tag->attributes->item($i)->value;
00367           $name  = str_replace(' ', '_', $tag->attributes->item($i)->name);
00368           $this->name_parts[$name_part][$name]  = $value;
00369         }
00370       }
00371     }
00372 
00373     parent::__construct($dom_node, $citeproc);
00374   }
00375 
00376   function init_formatting() {
00377     $this->no_op = array();
00378     $this->format = array();
00379     $this->attributes['base'] = $this->get_attributes();
00380     $this->format['base']  = '';
00381     $this->format['family']  = '';
00382     $this->format['given']  = '';
00383     $this->no_op['base'] = TRUE;
00384     $this->no_op['family'] = TRUE;
00385     $this->no_op['given'] = TRUE;
00386 
00387     if (isset($this->attributes['prefix'])) $this->no_op['base'] = FALSE;
00388     if (isset($this->attributes['suffix'])) $this->no_op['base'] = FALSE;
00389     $this->init_format($this->attributes['base']);
00390 
00391 
00392     if (!empty($this->name_parts)) {
00393       foreach ($this->name_parts as $name => $formatting) {
00394         $this->init_format($formatting, $name);
00395       }
00396     }
00397   }
00398 
00399   function init_attrs($mode) {
00400  //   $and = $this->get_attributes('and');
00401     if (isset($this->attributes['and']) && $this->attributes['and'] == 'text') {
00402       $this->attributes['and'] = $this->citeproc->get_locale('term', 'and');
00403     }
00404     if (isset($this->attributes['and']) && $this->attributes['and'] == 'symbol') {
00405       $this->attributes['and'] = ' & ';
00406     }
00407     if (isset($this->citeproc)) {
00408       $style_attrs = $this->citeproc->style->get_hier_attributes();
00409       $mode_attrs = $this->citeproc->{$mode}->get_hier_attributes();
00410       $this->attributes = array_merge($style_attrs, $mode_attrs, $this->attributes);
00411     }
00412     if (!isset($this->attributes['delimiter'])) {
00413       $this->attributes['delimiter'] = (!empty($this->attributes['name-delimiter'])) ? $this->attributes['name-delimiter'] : ', ';
00414     }
00415     if (!isset($this->alnum)) {
00416       list($this->alnum, $this->alpha, $this->cntrl, $this->dash,
00417       $this->digit, $this->graph, $this->lower, $this->print,
00418       $this->punct, $this->space, $this->upper, $this->word,
00419       $this->patternModifiers) = $this->get_regex_patterns();
00420     }
00421     $this->dpl = $this->get_attributes('delimiter-precedes-last');
00422     $this->sort_separator = ($this->get_attributes('sort-separator'))? $this->get_attributes('sort-separator') : ', ';
00423     $this->form = ($this->get_attributes('form'))? $this->get_attributes('form') : 'long';
00424     $this->attr_init = $mode;
00425   }
00426 
00427   function init_format($attribs, $part = 'base') {
00428     if (isset($attribs['quotes'])) {
00429       $this->attributes[$part]['open-quote'] = $this->citeproc->get_locale('term', 'open-quote');
00430       $this->attributes[$part]['close-quote'] = $this->citeproc->get_locale('term', 'close-quote');
00431       $this->attributes[$part]['open-inner-quote'] = $this->citeproc->get_locale('term', 'open-inner-quote');
00432       $this->attributes[$part]['close-inner-quote'] = $this->citeproc->get_locale('term', 'close-inner-quote');
00433       $this->no_op[$part] = FALSE;
00434     }
00435 
00436     if (isset($attribs['prefix']))  $this->attributes[$part]['prefix'] = $attribs['prefix'];
00437     if (isset($attribs['suffix']))  $this->attributes[$part]['suffix'] = $attribs['suffix'];
00438 
00439     $this->format[$part] .= (isset($attribs['font-style']))      ? 'font-style: ' . $attribs['font-style'] . ';' : '';
00440     $this->format[$part] .= (isset($attribs['font-family']))     ? 'font-family: ' . $attribs['font-family'] . ';' : '';
00441     $this->format[$part] .= (isset($attribs['font-weight']))     ? 'font-weight: ' . $attribs['font-weight'] . ';' : '';
00442     $this->format[$part] .= (isset($attribs['font-variant']))    ? 'font-variant: ' . $attribs['font-variant'] . ';' : '';
00443     $this->format[$part] .= (isset($attribs['text-decoration'])) ? 'text-decoration: ' . $attribs['text-decoration'] . ';' : '';
00444     $this->format[$part] .= (isset($attribs['vertical-align']))  ? 'vertical-align: ' . $attribs['vertical-align'] . ';' : '';
00445 
00446     if (isset($attribs['text-case']))  $this->no_op[$part] = FALSE;
00447     if (!empty($this->format[$part])) $this->no_op[$part] = FALSE;
00448 
00449   }
00450 
00451   function format($text, $part = 'base') {
00452 
00453     if (empty($text) || $this->no_op[$part]) return $text;
00454     if (isset($this->attributes[$part]['text-case'])) {
00455       switch ($this->attributes[$part]['text-case']) {
00456         case 'uppercase':
00457           $text = mb_strtoupper($text);
00458           break;
00459         case 'lowercase':
00460           $text = mb_strtolower($text);
00461           break;
00462         case 'capitalize-all':
00463           $text = mb_convert_case($text, MB_CASE_TITLE);
00464           break;
00465         case 'capitalize-first':
00466           $text[0] = mb_strtoupper($text[0]);
00467           break;
00468       }
00469     }
00470     $open_quote = (isset($this->attributes[$part]['open-quote'])) ? $this->attributes[$part]['open-quote'] : '';
00471     $close_quote = (isset($this->attributes[$part]['close-quote'])) ? $this->attributes[$part]['close-quote'] : '';
00472     $prefix = (isset($this->attributes[$part]['prefix'])) ? $this->attributes[$part]['prefix'] : '';
00473     $suffix = (isset($this->attributes[$part]['suffix'])) ? $this->attributes[$part]['suffix'] : '';
00474     if ($text[(strlen($text) -1)] == $suffix) unset($suffix);
00475     if (!empty($this->format[$part])) {
00476       $text = '<span style="' . $this->format[$part] . '">' . $text . '</span>';
00477     }
00478     return $prefix . $open_quote . $text . $close_quote . $suffix;
00479   }
00480 
00481   function render($names, $mode = NULL) {
00482     $text = '';
00483     $authors = array();
00484     $count = 0;
00485     $auth_count = 0;
00486     $et_al_triggered = FALSE;
00487     $initialize_with = $this->get_attributes('initialize-with');
00488 
00489     if (!$this->attr_init || $this->attr_init != $mode) $this->init_attrs($mode);
00490 
00491     foreach ($names as $rank => $name) {
00492       $count++;
00493       //$given = (!empty($name->firstname)) ? $name->firstname : '';
00494       if (!empty($name->given) && isset($initialize_with)) {
00495           $name->given = preg_replace("/([$this->upper])[$this->lower]+/$this->patternModifiers", '\\1', $name->given);
00496           $name->given = preg_replace("/(?<=[-$this->upper]) +(?=[-$this->upper])/$this->patternModifiers", "", $name->given);
00497           $name->initials = $name->given . $name->initials;
00498       }
00499       if (isset($name->initials)) {
00500         // within initials, remove any dots:
00501         $name->initials = preg_replace("/([$this->upper])\.+/$this->patternModifiers", "\\1", $name->initials);
00502         // within initials, remove any spaces *between* initials:
00503         $name->initials = preg_replace("/(?<=[-$this->upper]) +(?=[-$this->upper])/$this->patternModifiers", "", $name->initials);
00504         // within initials, add a space after a hyphen, but only if ...
00505         if (ereg(" $", $initialize_with)) {// ... the delimiter that separates initials ends with a space
00506           $name->initials = preg_replace("/-(?=[$this->upper])/$this->patternModifiers", "- ", $name->initials);
00507         }
00508         // then, separate initials with the specified delimiter:
00509         $name->initials = preg_replace("/([$this->upper])(?=[^$this->lower]+|$)/$this->patternModifiers", "\\1$initialize_with", $name->initials);
00510 
00511         //      $shortenInitials = (isset($options['numberOfInitialsToKeep'])) ? $options['numberOfInitialsToKeep'] : FALSE;
00512         //      if ($shortenInitials) $given = drupal_substr($given, 0, $shortenInitials);
00513 
00514         if (isset($initialize_with) ) {
00515           $name->given = $name->initials;
00516           if ($shortenInitials) $name->given = drupal_substr($name->given, 0, $shortenInitials);
00517         }
00518         elseif(!empty($name->given)) {
00519           $name->given = $name->given.' '.$name->initials;
00520         }
00521         elseif(empty($name->given)) {
00522           $name->given = $name->initials;
00523         }
00524       }
00525 
00526 
00527       if (isset($name->given)) {
00528         $given = $this->format($name->given, 'given');
00529       }
00530       if(isset($name->family)) {
00531         $name->family = $this->format($name->family, 'family');
00532         if ($this->get_attributes('form') == 'short') {
00533           $text = $name->family;
00534         }
00535         else {
00536           switch ($this->get_attributes('name-as-sort-order')) {
00537             case 'first':
00538             case 'all':
00539               $text = $name->family . $this->sort_separator . $given;
00540               break;
00541             default:
00542               $text = $given .' '. $name->family ;
00543           }
00544         }
00545         $authors[] = $this->format($text);
00546       }
00547       if (isset($this->attributes['et-al-min']) && $count >= $this->attributes['et-al-min']) break;
00548     }
00549     if (isset($this->attributes['et-al-min']) &&
00550         $count >= $this->attributes['et-al-min'] &&
00551         isset($this->attributes['et-al-use-first'])) {
00552       if ($this->attributes['et-al-use-first'] < $this->attributes['et-al-min']) {
00553         for ($i = $this->attributes['et-al-use-first']; $i < $count; $i++) {
00554           unset($authors[$i]);
00555         }
00556       }
00557       $authors[] = $this->citeproc->get_locale('term', 'et-al');
00558       $et_al_triggered = TRUE;
00559     }
00560 
00561     if (!empty($authors) && !$et_al_triggered) {
00562       $auth_count = count($authors);
00563       if (isset($this->attributes['and']) && $auth_count > 1) {
00564         $authors[$auth_count-1] = $this->attributes['and'] .' '. $authors[$auth_count-1]; //stick an "and" in front of the last author if "and" is defined
00565       }
00566     }
00567     $text = implode($this->attributes['delimiter'], $authors);
00568 
00569     // strip out the last delimiter if not required
00570     if (isset($this->attributes['and']) && $auth_count > 1) {
00571       $last_delim =  strrpos($text, $this->attributes['delimiter']);
00572       switch ($this->dpl) { //dpl == delimiter proceeds last
00573         case 'never':
00574           return substr_replace($text, '', $last_delim, strlen($this->attributes['delimiter']));
00575           break;
00576         case 'contextual':
00577         default:
00578           if ($auth_count < 3) {
00579             return substr_replace($text, '', $last_delim, strlen($this->attributes['delimiter']));
00580           }
00581       }
00582     }
00583 
00584     return $text;
00585   }
00586 
00587   function get_regex_patterns() {
00588     // Checks if PCRE is compiled with UTF-8 and Unicode support
00589     if (!@preg_match('/\pL/u', 'a')) {
00590       // probably a broken PCRE library
00591       return $this->get_latin1_regex();
00592     }
00593     else {
00594       // Unicode safe filter for the value
00595       return $this->get_utf8_regex();
00596     }
00597   }
00598 
00599   function get_latin1_regex() {
00600     $alnum = "[:alnum:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß";
00601     // Matches ISO-8859-1 letters:
00602     $alpha = "[:alpha:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß";
00603     // Matches ISO-8859-1 control characters:
00604     $cntrl = "[:cntrl:]";
00605     // Matches ISO-8859-1 dashes & hyphens:
00606     $dash = "-–";
00607     // Matches ISO-8859-1 digits:
00608     $digit = "[\d]";
00609     // Matches ISO-8859-1 printing characters (excluding space):
00610     $graph = "[:graph:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß";
00611     // Matches ISO-8859-1 lower case letters:
00612     $lower = "[:lower:]äåáàâãçéèêëñöøóòôõüúùûíìîïæÿß";
00613     // Matches ISO-8859-1 printing characters (including space):
00614     $print = "[:print:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß";
00615     // Matches ISO-8859-1 punctuation:
00616     $punct = "[:punct:]";
00617     // Matches ISO-8859-1 whitespace (separating characters with no visual representation):
00618     $space = "[\s]";
00619     // Matches ISO-8859-1 upper case letters:
00620     $upper = "[:upper:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆ";
00621     // Matches ISO-8859-1 "word" characters:
00622     $word = "_[:alnum:]ÄÅÁÀÂÃÇÉÈÊËÑÖØÓÒÔÕÜÚÙÛÍÌÎÏÆäåáàâãçéèêëñöøóòôõüúùûíìîïæÿß";
00623     // Defines the PCRE pattern modifier(s) to be used in conjunction with the above variables:
00624     // More info: <http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php>
00625     $patternModifiers = "";
00626 
00627     return array($alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower,
00628                  $print, $punct, $space, $upper, $word, $patternModifiers);
00629 
00630   }
00631   function get_utf8_regex() {
00632     // Matches Unicode letters & digits:
00633     $alnum = "\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}"; // Unicode-aware equivalent of "[:alnum:]"
00634     // Matches Unicode letters:
00635     $alpha = "\p{Ll}\p{Lu}\p{Lt}\p{Lo}"; // Unicode-aware equivalent of "[:alpha:]"
00636     // Matches Unicode control codes & characters not in other categories:
00637     $cntrl = "\p{C}"; // Unicode-aware equivalent of "[:cntrl:]"
00638     // Matches Unicode dashes & hyphens:
00639     $dash = "\p{Pd}";
00640     // Matches Unicode digits:
00641     $digit = "\p{Nd}"; // Unicode-aware equivalent of "[:digit:]"
00642     // Matches Unicode printing characters (excluding space):
00643     $graph = "^\p{C}\t\n\f\r\p{Z}"; // Unicode-aware equivalent of "[:graph:]"
00644     // Matches Unicode lower case letters:
00645     $lower = "\p{Ll}\p{M}"; // Unicode-aware equivalent of "[:lower:]"
00646     // Matches Unicode printing characters (including space):
00647     $print = "\P{C}"; // same as "^\p{C}", Unicode-aware equivalent of "[:print:]"
00648     // Matches Unicode punctuation (printing characters excluding letters & digits):
00649     $punct = "\p{P}"; // Unicode-aware equivalent of "[:punct:]"
00650     // Matches Unicode whitespace (separating characters with no visual representation):
00651     $space = "\t\n\f\r\p{Z}"; // Unicode-aware equivalent of "[:space:]"
00652     // Matches Unicode upper case letters:
00653     $upper = "\p{Lu}\p{Lt}"; // Unicode-aware equivalent of "[:upper:]"
00654     // Matches Unicode "word" characters:
00655     $word = "_\p{Ll}\p{Lu}\p{Lt}\p{Lo}\p{Nd}"; // Unicode-aware equivalent of "[:word:]" (or "[:alnum:]" plus "_")
00656     // Defines the PCRE pattern modifier(s) to be used in conjunction with the above variables:
00657     // More info: <http://www.php.net/manual/en/reference.pcre.pattern.modifiers.php>
00658     $patternModifiers = "u"; // the "u" (PCRE_UTF8) pattern modifier causes PHP/PCRE to treat pattern strings as UTF-8
00659     return array($alnum, $alpha, $cntrl, $dash, $digit, $graph, $lower,
00660                  $print, $punct, $space, $upper, $word, $patternModifiers);
00661   }
00662 
00663 }
00664 
00665 class csl_names extends csl_format {
00666   private $substitutes;
00667 
00668   function init($dom_node, $citeproc) {
00669 
00670     $tag = $dom_node->getElementsByTagName('substitute')->item(0);
00671     if ($tag) {
00672       $this->substitutes = csl_factory::create($tag, $citeproc);
00673       $dom_node->removeChild($tag);
00674     }
00675 
00676     $var = $dom_node->getAttribute('variable');
00677     foreach ($dom_node->childNodes as $node) {
00678       if ($node->nodeType == 1) {
00679         $element = csl_factory::create($node, $citeproc);
00680         if (($element instanceof csl_label)) $element->set_attribute('variable', $var);
00681         $this->add_element($element);
00682       }
00683     }
00684   }
00685 
00686   function render($data, $mode) {
00687     $matches = 0;
00688     $variable_parts = array();
00689     if (!isset($this->attributes['delimiter'])) {
00690       $style_delimiter = $this->citeproc->style->get_attributes('names-delimiter');
00691       $mode_delimiter = $this->citeproc->{$mode}->get_attributes('names-delimiter');
00692       $this->attributes['delimiter'] = (!empty($mode_delimiter)) ? $mode_delimiter : (!empty($style_delimiter)? $style_delimiter : '');
00693     }
00694 
00695     $variables  = explode(' ', $this->get_attributes('variable'));
00696     foreach ($variables as $var) {
00697       if (isset($data->{$var}) && (!empty($data->{$var}))) {
00698         $matches++;
00699         break;
00700       }
00701     }
00702 
00703     if (!$matches) { // we don't have any primary suspects, so lets check the substitutes...
00704       if (isset($this->substitutes)) {
00705         foreach ($this->substitutes->elements as $element) {
00706           if (($element instanceof csl_names)) { //test to see if any of the other names variables has content
00707             $variables  = explode(' ', $element->get_attributes('variable'));
00708             foreach ($variables as $var) {
00709               //list($contributor, $type) = explode(':', $var);
00710               if (isset($data->{$var}) ) {
00711                 $matches++;
00712                 break;
00713               }
00714             }
00715           }
00716           else { // if it's not a "names" element, just render it
00717             return $element->render($data, $mode);
00718           }
00719         }
00720       }
00721     }
00722 
00723     foreach ($variables as $var) {
00724       $text = '';
00725       if (!empty($data->{$var})) {
00726         foreach ($this->elements as $element) {
00727           $text .= $element->render($data->{$var}, $mode);
00728         }
00729       }
00730       if (!empty($text)) $variable_parts[] = $text;
00731     }
00732 
00733     if (!empty($variable_parts)) {
00734       $text = implode($this->attributes['delimiter'], $variable_parts);
00735       return $this->format($text);
00736     }
00737 
00738     return ;
00739   }
00740 }
00741 
00742 class csl_date extends csl_format {
00743 
00744   function init($dom_node, $citeproc) {
00745     $locale_elements = array();
00746 
00747     if ($form = $this->get_attributes('form')) {
00748       $local_date = $this->citeproc->get_locale('date_options', $form);
00749       $dom_elem = dom_import_simplexml($local_date[0]);
00750       if ($dom_elem) {
00751         foreach ($dom_elem->childNodes as $node) {
00752           if ($node->nodeType == 1) {
00753             $locale_elements[] = csl_factory::create($node, $citeproc);
00754           }
00755         }
00756       }
00757       foreach ($dom_node->childNodes as $node) {
00758         if ($node->nodeType == 1) {
00759           $element = csl_factory::create($node, $citeproc);
00760 
00761           foreach ($locale_elements as $key => $locale_element) {
00762             if ($locale_element->attributes['name'] == $element->attributes['name']) {
00763               $locale_elements[$key]->attributes = array_merge($locale_element->attributes, $element->attributes);
00764               $locale_elements[$key]->format =  $element->format;
00765               break;
00766             }
00767 
00768             else {
00769               $locale_elements[] = $element;
00770             }
00771           }
00772         }
00773       }
00774       if ($date_parts = $this->get_attributes("date-parts")) {
00775         $parts = explode('-', $date_parts);
00776         foreach ($locale_elements as $key => $element) {
00777           if (array_search($element->attributes['name'], $parts) === FALSE) {
00778             unset($locale_elements[$key]);
00779           }
00780         }
00781         if (count($locale_elements) != count($parts)) {
00782           foreach ($parts as $part) {
00783             $element = new csl_date_part();
00784             $element->set_attribute('name', $part);
00785             $locale_elements[] = $element;
00786           }
00787         }
00788         // now re-order the elements
00789         foreach ($parts as $part) {
00790           foreach ($locale_elements as $key => $element)
00791           if ($element->attributes['name'] == $part) {
00792             $this->elements[] = $element;
00793             unset($locale_elements[$key]);
00794           }
00795         }
00796 
00797       }
00798       else {
00799         $this->elements = $locale_elements;
00800       }
00801     }
00802     else {
00803       parent::init($dom_node, $citeproc);
00804     }
00805 
00806 
00807   }
00808 
00809   function render($data, $mode) {
00810     $date_parts = array();
00811     $date = '';
00812     $text = '';
00813 
00814     if (($var = $this->get_attributes('variable')) && isset($data->{$var})) {
00815       $date = $data->{$var}->{'date-parts'}[0];
00816       foreach ($this->elements as $element) {
00817         $date_parts[] = $element->render($date, $mode);
00818       }
00819       $text = implode('', $date_parts);
00820     }else {
00821       $text = $this->citeproc->get_locale('term', 'no date');
00822     }
00823 
00824     return $this->format($text);
00825   }
00826 }
00827 
00828 class csl_date_part extends csl_format {
00829 
00830   function render($date, $mode) {
00831     $text = '';
00832 
00833     switch ($this->get_attributes('name')) {
00834       case 'year':
00835         $text = (isset($date[0])) ? $date[0] : '';
00836         if ($text > 0 && $text < 500) {
00837           $text = $text . $this->citeproc->get_locale('term', 'ad');
00838         }
00839         elseif ($text < 0) {
00840           $text = $text * -1;
00841           $text = $text . $this->citeproc->get_locale('term', 'bc');
00842         }
00843         //return ((isset($this->prefix))? $this->prefix : '') . $date[0] . ((isset($this->suffix))? $this->suffix : '');
00844         break;
00845       case 'month':
00846         $text = (isset($date[1])) ? $date[1] : '';
00847         if (empty($text) || $text < 1 || $text > 12) return;
00848         $form = $this->get_attributes('form');
00849         switch ($form) {
00850           case 'numeric': break;
00851           case 'numeric-leading-zeros':
00852             if ($text < 10) {
00853               $text = '0' . $text;
00854               break;
00855             }
00856             break;
00857           case 'short':
00858             $month = 'month-' . sprintf('%02d', $text);
00859             $text = $this->citeproc->get_locale('term', $month, 'short');
00860             break;
00861           default:
00862             $month = 'month-' . sprintf('%02d', $text);
00863             $text = $this->citeproc->get_locale('term', $month);
00864             break;
00865         }
00866         break;
00867       case 'day':
00868         $text = (isset($date[2])) ? $date[2] : '';
00869         break;
00870     }
00871 
00872     return $this->format($text);
00873   }
00874 }
00875 
00876 class csl_number extends csl_format {
00877 
00878   function render($data, $mode) {
00879     $var = $this->get_attributes('variable');
00880 
00881     if (!$var || empty($data->$var)) return;
00882 
00883     $form = $this->get_attributes('form');
00884 
00885     switch ($form) {
00886       case 'ordinal':
00887         $text = $this->ordinal($data->$var);
00888         break;
00889       case 'long-ordinal':
00890         $text = $this->long_ordinal($data->$var);
00891         break;
00892       case 'roman':
00893         $text = $this->roman($data->$var);
00894         break;
00895       case 'numeric':
00896       default:
00897         $text = $data->$var;
00898         break;
00899     }
00900     return $this->format($text);
00901   }
00902 
00903   function ordinal($num) {
00904     if ( ($num/10)%10 == 1) {
00905       $num .= $this->citeproc->get_locale('term', 'ordinal-04');
00906     }
00907     elseif ( $num%10 == 1) {
00908       $num .= $this->citeproc->get_locale('term', 'ordinal-01');
00909     }
00910     elseif ( $num%10 == 2) {
00911       $num .= $this->citeproc->get_locale('term', 'ordinal-02');
00912     }
00913     elseif ( $num%10 == 3) {
00914       $num .= $this->citeproc->get_locale('term', 'ordinal-03');
00915     }
00916     else {
00917       $num .= $this->citeproc->get_locale('term', 'ordinal-04');
00918     }
00919     return $num;
00920 
00921   }
00922 
00923   function long_ordinal($num) {
00924     $num = sprintf("%02d", $num);
00925     $ret = $this->citeproc->get_locale('term', 'long-ordinal-' . $num);
00926     if (!$ret) {
00927       return $this->ordinal($num);
00928     }
00929     return $ret;
00930   }
00931 
00932   function roman($num) {
00933     $ret = "";
00934     if ($num < 6000) {
00935       $ROMAN_NUMERALS = array(
00936       array( "", "i", "ii", "iii", "iv", "v", "vi", "vii", "viii", "ix" ),
00937       array( "", "x", "xx", "xxx", "xl", "l", "lx", "lxx", "lxxx", "xc" ),
00938       array( "", "c", "cc", "ccc", "cd", "d", "dc", "dcc", "dccc", "cm" ),
00939       array( "", "m", "mm", "mmm", "mmmm", "mmmmm")
00940       );
00941       $numstr = strrev($num);
00942       $len = strlen($numstr);
00943       for ($pos = 0; $pos < $len; $pos++) {
00944         $n = $numstr[$pos];
00945         $ret = $ROMAN_NUMERALS[$pos][$n] . $ret;
00946       }
00947     }
00948 
00949     return $ret;
00950   }
00951 
00952 }
00953 
00954 class csl_text extends csl_format {
00955   public $source;
00956   protected $var;
00957 
00958   function init($dom_node, $citeproc) {
00959     foreach (array('variable', 'macro', 'term', 'value') as $attr) {
00960       if ($dom_node->hasAttribute($attr)) {
00961         $this->source = $attr;
00962         if ($this->source == 'macro') {
00963           $this->var =  str_replace(' ', '_', $dom_node->getAttribute($attr));
00964         }
00965         else {
00966           $this->var =  $dom_node->getAttribute($attr);
00967         }
00968       }
00969     }
00970   }
00971 
00972   function render($data, $mode) {
00973     $text = '';
00974 
00975     switch ($this->source) {
00976       case 'variable':
00977         if(!isset($data->{$this->attributes['variable']})) return;
00978         $text = $data->{$this->attributes['variable']}; //$this->data[$this->var];  // include the contents of a variable
00979         break;
00980       case 'macro':
00981         $macro = $this->var;
00982         $text = $this->citeproc->render_macro($macro, $data, $mode); //trigger the macro process
00983         break;
00984       case 'term':
00985         $form = (($form = $this->get_attributes('form'))) ? $form : '';
00986         $text = $this->citeproc->get_locale('term', $this->var, $form);
00987         break;
00988       case 'value':
00989         $text = $this->var; //$this->var;  // dump the text verbatim
00990         break;
00991     }
00992 
00993     if (empty($text)) return;
00994     return $this->format($text);
00995   }
00996 }
00997 
00998 class csl_label extends csl_format {
00999   private $plural;
01000 
01001   function render($data, $mode) {
01002     $text = '';
01003 
01004     $variables = explode(' ', $this->get_attributes('variable'));
01005     $form = (($form = $this->get_attributes('form'))) ? $form : 'long';
01006     $plural = (($plural = $this->get_attributes('plural'))) ? $plural : 'contextual';
01007     switch ($this->get_attributes('plural')) {
01008       case 'never':
01009         $plural = 'single';
01010         break;
01011       case 'always':
01012         $plural = 'multiple';
01013         break;
01014       case 'contextual':
01015       default:
01016         if (count($data) == 1) {
01017           $plural = 'single';
01018         }
01019         elseif (count($data) > 1) {
01020           $plural = 'multiple';
01021         }
01022     }
01023     foreach ($variables as $variable) {
01024       if (($term = $this->citeproc->get_locale('term', $variable, $form, $plural))) {
01025         $text = $term;
01026         break;
01027       }
01028     }
01029 
01030     if (empty($text)) return;
01031     if ($this->get_attributes('strip-periods')) $text = str_replace('.', '', $text);
01032     return $this->format($text);
01033   }
01034 }
01035 
01036 class csl_macro extends csl_format{
01037 
01038 }
01039 
01040 class csl_macros extends csl_collection{
01041 
01042   function __construct($macro_nodes, $citeproc) {
01043     foreach ($macro_nodes as $macro) {
01044       $macro = csl_factory::create($macro, $citeproc);
01045       $this->elements[$macro->name()] = $macro;
01046     }
01047   }
01048 
01049   function render_macro($name, $data, $mode) {
01050     return $this->elements[$name]->render($data, $mode);
01051   }
01052 }
01053 
01054 class csl_group extends csl_format{
01055 
01056   function render($data, $mode) {
01057     $text = '';
01058     $text_parts = array();
01059 
01060     $terms=0;
01061     foreach ($this->elements as $element) {
01062       if (($element instanceof csl_text) &&
01063           ($element->source == 'term' ||
01064            $element->source == 'value' ||
01065            $element->source == 'variable')) {
01066         $terms++;
01067       }
01068       $text = $element->render($data, $mode);
01069       if (!empty($text)) {
01070         $text_parts[] = $text;
01071       }
01072     }
01073 
01074     if (empty($text_parts)) return;
01075     if ($terms && count($text_parts) <= $terms) return; // there has to be at least one other none empty value before the term is output
01076 
01077     $delimiter = $this->get_attributes('delimiter');
01078     $text = implode($delimiter, $text_parts); // insert the delimiter if supplied.
01079 
01080 
01081     return $this->format($text);
01082   }
01083 }
01084 
01085 class csl_layout extends csl_format {
01086 
01087   function render($data, $mode) {
01088     $text = '';
01089     $parts = array();
01090     $delimiter = $this->get_attributes('delimiter');
01091 
01092     foreach ($this->elements as $element) {
01093       $parts[] = $element->render($data, $mode);
01094     }
01095 
01096     $text = implode($delimiter, $parts);
01097 
01098     return $this->format($text);
01099   }
01100 
01101 }
01102 
01103 class csl_citation extends csl_element{
01104   private $layout = NULL;
01105 
01106   function init($dom_node, $citeproc) {
01107     $options = $dom_node->getElementsByTagName('option');
01108     foreach ($options as $option) {
01109       $value = $option->getAttribute('value');
01110       $name  = $option->getAttribute('name');
01111       $this->attributes[$name]  = $value;
01112     }
01113 
01114     $layouts = $dom_node->getElementsByTagName('layout');
01115     foreach ($layouts as $layout) {
01116       $this->layout = new csl_layout($layout, $citeproc);
01117     }
01118   }
01119 
01120   function render($data, $mode = NULL) {
01121     $text = $this->layout->render($data, 'citation');
01122 
01123     return $text;
01124   }
01125 
01126 }
01127 class csl_bibliography  extends csl_element {
01128   private $layout = NULL;
01129 
01130   function init($dom_node, $citeproc) {
01131     $hier_name_attr = $this->get_hier_attributes();
01132     $options = $dom_node->getElementsByTagName('option');
01133     foreach ($options as $option) {
01134       $value = $option->getAttribute('value');
01135       $name  = $option->getAttribute('name');
01136       $this->attributes[$name]  = $value;
01137     }
01138 
01139     $layouts = $dom_node->getElementsByTagName('layout');
01140     foreach ($layouts as $layout) {
01141       $this->layout = new csl_layout($layout, $citeproc);
01142     }
01143 
01144   }
01145 
01146   function render($data, $mode = NULL) {
01147     $text = $this->layout->render($data, 'bibliography');
01148     if ($this->get_attributes('hanging-indent') == 'true') {
01149       $text = '<div style="  text-indent: -25px; padding-left: 25px;">' . $text . '</div>';
01150     }
01151     $text = str_replace('?.', '?', str_replace('..', '.', $text));
01152     return $text;
01153   }
01154 }
01155 
01156 class csl_option  {
01157   private $name;
01158   private $value;
01159 
01160   function get() {
01161     return array($this->name => $this->value);
01162   }
01163 }
01164 
01165 class csl_options extends csl_element{
01166 
01167 }
01168 
01169 class csl_sort extends csl_element{
01170 
01171 }
01172 class csl_style extends csl_element{
01173 
01174   function __construct($dom_node = NULL, $citeproc = NULL) {
01175     if ($dom_node) {
01176       $this->attributes = $this->set_attributes($dom_node);
01177     }
01178   }
01179 }
01180 
01181 class csl_choose extends csl_element{
01182 
01183   function render($data, $mode) {
01184     foreach ($this->elements as $choice) {
01185       if ($choice->evaluate($data)) {
01186         return $choice->render($data, $mode);
01187       }
01188     }
01189   }
01190 }
01191 
01192 class csl_if extends csl_rendering_element {
01193 
01194   function evaluate($data) {
01195     $match = (($match = $this->get_attributes('match'))) ? $match : 'all';
01196     if (($types = $this->get_attributes('type'))) {
01197       $types  = explode(' ', $types);
01198       $matches = 0;
01199       foreach ($types as $type) {
01200         if (isset($data->type)) {
01201           if ($data->type == $type && $match == 'any') return TRUE;
01202           if ($data->type != $type && $match == 'all') return FALSE;
01203           if ($data->type == $type) $matches++;
01204         }
01205       }
01206       if ($match == 'all' && $matches = count($types)) return TRUE;
01207       if ($match == 'none' && $matches = 0) return TRUE;
01208       return FALSE;
01209     }
01210     if (($variables = $this->get_attributes('variable'))) {
01211       $variables  = explode(' ', $variables);
01212       $matches = 0;
01213       foreach ($variables as $var) {
01214         if (isset($data->$var) && $match == 'any') return TRUE;
01215         if (!isset($data->$var) && $match == 'all') return FALSE;
01216         if (isset($data->$var)) $matches++;
01217       }
01218       if ($match == 'all' && $matches = count($variables)) return TRUE;
01219       if ($match == 'none' && $matches = 0) return TRUE;
01220       return FALSE;
01221     }
01222     if (($is_numeric = $this->get_attributes('is-numeric'))) {
01223       $variables  = explode(' ', $is_numeric);
01224       $matches = 0;
01225       foreach ($variables as $var) {
01226         if (isset($data->$var)) {
01227           if (is_numeric($data->$var) && $match == 'any') return TRUE;
01228           if (!is_numeric($data->$var) && $match == 'all') return FALSE;
01229           if (is_numeric($data->$var)) $matches++;
01230         }
01231       }
01232       if ($match == 'all' && $matches == count($variables)) return TRUE;
01233       if ($match == 'none' && $matches == 0) return TRUE;
01234       return FALSE;
01235     }
01236     if (isset($this->locator))  $test  = explode(' ', $this->type);
01237 
01238     return FALSE;
01239   }
01240 }
01241 
01242 class csl_else_if extends csl_if {
01243 
01244 }
01245 
01246 class csl_else extends csl_if {
01247 
01248   function evaluate($data = NULL) {
01249     return TRUE; // the last else always returns TRUE
01250   }
01251 }
01252 
01253 class csl_substitute extends csl_element{
01254 
01255 }
01256 
01257 class csl_locale  {
01258   protected $locale_xmlstring = NULL;
01259   protected $style_locale_xmlstring = NULL;
01260   protected $locale = NULL;
01261   protected $style_locale = NULL;
01262   private   $module_path;
01263 
01264   function __construct($lang = 'en') {
01265     $this->module_path = '.';
01266     $this->locale = new SimpleXMLElement($this->get_locales_file_name($lang));
01267     if ($this->locale) {
01268       $this->locale->registerXPathNamespace('cs', 'http://purl.org/net/xbiblio/csl');
01269     }
01270   }
01271 
01272   // SimpleXML objects cannot be serialized, so we must convert to an XML string prior to serialization
01273   function __sleep() {
01274     $this->locale_xmlstring       = ($this->locale)       ? $this->locale->asXML()       : '';
01275     $this->style_locale_xmlstring = ($this->style_locale) ? $this->style_locale->asXML() : '';
01276     return array('locale_xmlstring', 'style_locale_xmlstring');
01277   }
01278 
01279   // SimpleXML objects cannot be serialized, so when un-serializing them, they must rebuild from the serialized XML string.
01280   function __wakeup() {
01281     $this->style_locale = (!empty($this->style_locale_xmlstring)) ? new SimpleXMLElement($this->style_locale_xmlstring) : NULL;
01282     $this->locale       = (!empty($this->locale_xmlstring))       ? new SimpleXMLElement($this->locale_xmlstring)       : NULL;
01283     if ($this->locale) {
01284       $this->locale->registerXPathNamespace('cs', 'http://purl.org/net/xbiblio/csl');
01285     }
01286   }
01287 
01288   function get_locales_file_name($lang) {
01289     $lang_bases = array(
01290         "af" => "af-ZA",
01291         "ar" => "ar-AR",
01292         "bg" => "bg-BG",
01293         "ca" => "ca-AD",
01294         "cs" => "cs-CZ",
01295         "da" => "da-DK",
01296         "de" => "de-DE",
01297         "el" => "el-GR",
01298         "en" => "en-US",
01299         "es" => "es-ES",
01300         "et" => "et-EE",
01301         "fr" => "fr-FR",
01302         "he" => "he-IL",
01303         "hu" => "hu-HU",
01304         "is" => "is-IS",
01305         "it" => "it-IT",
01306         "ja" => "ja-JP",
01307         "ko" => "ko-KR",
01308         "mn" => "mn-MN",
01309         "nb" => "nb-NO",
01310         "nl" => "nl-NL",
01311         "pl" => "pl-PL",
01312         "pt" => "pt-PT",
01313         "ro" => "ro-RO",
01314         "ru" => "ru-RU",
01315         "sk" => "sk-SK",
01316         "sl" => "sl-SI",
01317         "sr" => "sr-RS",
01318         "sv" => "sv-SE",
01319         "th" => "th-TH",
01320         "tr" => "tr-TR",
01321         "uk" => "uk-UA",
01322         "vi" => "vi-VN",
01323         "zh" => "zh-CN",
01324     );
01325     return (isset($lang_bases[$lang])) ? file_get_contents($this->module_path . '/locale/locales-' . $lang_bases[$lang] . '.xml') : file_get_contents($this->module_path . '/locale/locales-en-US.xml');
01326   }
01327 
01328   function get_locale($type, $arg1, $arg2 = NULL, $arg3 = NULL) {
01329     switch ($type) {
01330       case 'term':
01331         $term = '';
01332         $form = $arg2 ? " and @form='$arg2'" : '';
01333         $plural = $arg3 ? "/cs:$arg3" : '';
01334         if ($this->style_locale) {
01335           $term = $this->style_locale->xpath("//locale[@xml:lang='en']/terms/term[@name='$arg1'$form]$plural");
01336           if (!$term) {
01337             $term = $this->style_locale->xpath("//locale/terms/term[@name='$arg1'$form]$plural");
01338           }
01339         }
01340         if (!$term) {
01341           $term = $this->locale->xpath("//cs:term[@name='$arg1'$form]$plural");
01342         }
01343         if (isset($term[0])) return (string)$term[0];
01344         break;
01345       case 'date_option':
01346         $attribs = array();
01347         if ($this->style_locale) {
01348           $date_part = $this->style_locale->xpath("//date[@form='$arg1']/date-part[@name='$arg2']");
01349         }
01350         if (!isset($date_part)) {
01351           $date_part = $this->locale->xpath("//cs:date[@form='$arg1']/cs:date-part[@name='$arg2']");
01352         }
01353         if (isset($date_part)) {
01354           foreach ($$date_part->attributes()  as $name => $value) {
01355             $attribs[$name] = (string)$value;
01356           }
01357         }
01358         return $attribs;
01359         break;
01360       case 'date_options':
01361         if ($this->style_locale) {
01362           $options = $this->style_locale->xpath("//locale[@xml:lang='en']/date[@form='$arg1']");
01363           if (!$options) {
01364             $options = $this->style_locale->xpath("//locale/date[@form='$arg1']");
01365           }
01366         }
01367         if (!$options) {
01368           $options = $this->locale->xpath("//cs:date[@form='$arg1']");
01369         }
01370         if (isset($options[0]))return $options[0];
01371         break;
01372       case 'style_option':
01373         $attribs = array();
01374         if ($this->style_locale) {
01375           $option = $this->style_locale->xpath("//locale[@xml:lang='en']/style-options[@$arg1]");
01376           if (!$option) {
01377             $option = $this->style_locale->xpath("//locale/style-options[@$arg1]");
01378           }
01379         }
01380         if (isset($option)) {
01381           $attribs = $option[0]->attributes();
01382         }
01383         if (empty($attribs)) {
01384           $option = $this->locale->xpath("//cs:style-options[@$arg1]");
01385         }
01386         foreach ($option[0]->attributes()  as $name => $value) {
01387           if ($name == $arg1) return (string)$value;
01388         }
01389         break;
01390     }
01391   }
01392 
01393   public function set_style_locale($csl_doc) {
01394     $xml = '';
01395     $locale_nodes = $csl_doc->getElementsByTagName('locale');
01396     if ($locale_nodes) {
01397       $xml_open = '<style-locale>';
01398       $xml_close = '</style-locale>';
01399       foreach ($locale_nodes as $key => $locale_node) {
01400         $xml .= $csl_doc->saveXML($locale_node);
01401       }
01402       if (!empty($xml)) {
01403         $this->style_locale = new SimpleXMLElement($xml_open . $xml . $xml_close);
01404       }
01405     }
01406   }
01407 
01408 }
01409 
01410 class csl_mapper {
01411 
01412   function map_field($field) {
01413     if (!isset($this->field_map)) {
01414       $this->field_map = array('title' => 'title',
01415                                 'container-title' => 'biblio_secondary_title',
01416                                 'collection-title' => 'biblio_secondary_title',
01417                                 'original-title' => 'biblio_alternate_title',
01418                                 'publisher' => 'biblio_publisher',
01419                                 'publisher-place' => 'biblio_place_published',
01420                                 'original-publisher' => 'no_match',
01421                                 'original-publisher-place' => 'no_match',
01422                                 'archive' => 'no_match',
01423                                 'archive-place' => 'no_match',
01424                                 'authority' => 'no_match',
01425                                 'archive_location' => 'no_match',
01426                                 'event' => 'biblio_secondary_title',
01427                                 'event-place' => 'biblio_place_published',
01428                                 'page' => 'biblio_pages',
01429                                 'page-first' => 'no_match',
01430                                 'locator' => 'no_match',
01431                                 'version' => 'biblio_edition',
01432                                 'volume' => 'biblio_volume',
01433                                 'number-of-volumes' => 'biblio_number_of_volumes',
01434                                 'number-of-pages' => 'no_match',
01435                                 'issue' => 'biblio_issue',
01436                                 'chapter-number' => 'biblio_section',
01437                                 'medium' => 'no_match',
01438                                 'status' => 'no_match',
01439                                 'edition' => 'biblio_edition',
01440                                 'section' => 'biblio_section',
01441                                 'genre' => 'no_match',
01442                                 'note' => 'biblio_notes',
01443                                 'annote' => 'no_match',
01444                                 'abstract'  => 'biblio_abst_e',
01445                                 'keyword' => 'biblio_keywords',
01446                                 'number' => 'biblio_number',
01447                                 'references' => 'no_match',
01448                                 'URL' => 'biblio_url',
01449                                 'DOI' => 'biblio_doi',
01450                                 'ISBN' => 'biblio_isbn',
01451                                 'call-number' => 'biblio_call_number',
01452                                 'citation-number' => 'no_match',
01453                                 'citation-label' => 'biblio_citekey',
01454                                 'first-reference-note-number' => 'no_match',
01455                                 'year-suffix' => 'no_match',
01456                                 'jurisdiction' => 'no_match',
01457 
01458       //Date Variables'
01459 
01460                                 'issued' => 'biblio_year',
01461                                 'event' => 'biblio_date',
01462                                 'accessed' => 'biblio_accessed',
01463                                 'container' => 'biblio_date',
01464                                 'original-date' => 'biblio_date',
01465 
01466                                     //Name Variables'
01467 
01468                                 'author' => 'biblio_contributors:1',
01469                                 'editor' => 'biblio_contributors:2',
01470                                 'translator' => 'biblio_contributors:3',
01471                                 'recipient' => 'no_match',
01472                                 'interviewer' => 'biblio_contributors:1',
01473                                 'publisher' => 'biblio_publisher',
01474                                 'composer' => 'biblio_contributors:1',
01475                                 'original-publisher' => '',
01476                                 'original-author' => '',
01477                                 'container-author' => '',
01478                                 'collection-editor' => '',
01479                               );
01480     }
01481     $vars = explode(' ', $field);
01482     foreach ($vars as $key => $value) {
01483       $vars[$key] = (!empty($this->field_map[$value])) ? $this->field_map[$value] : '';
01484     }
01485 
01486     return implode(' ', $vars);
01487   }
01488 
01489   function map_type($types) {
01490     if (!isset($this->type_map)) {
01491       $this->type_map = array(
01492                         'article' => '',
01493                         'article-magazine'  => 106,
01494                         'article-newspaper' => 105,
01495                         'article-journal' => 102,
01496                         'bill' => 117,
01497                         'book'  => 100,
01498                         'broadcast' => 111,
01499                         'chapter' => 101,
01500                         'entry' => '',
01501                         'entry-dictionary'  => '',
01502                         'entry-encyclopedia'  => '',
01503                         'figure'  => '',
01504                         'graphic'  => '',
01505                         'interview'  => '',
01506                         'legislation' => 118,
01507                         'legal_case' => 128,
01508                         'manuscript' => 121,
01509                         'map' => 122,
01510                         'motion_picture' => 110,
01511                         'musical_score'  => '',
01512                         'pamphlet'  => '',
01513                         'paper-conference' => 103,
01514                         'patent' => 119,
01515                         'post'  => '',
01516                         'post-weblog'  => '',
01517                         'personal\_communication' => 120,
01518                         'report' => 109,
01519                         'review'  => '',
01520                         'review-book'  => '',
01521                         'song'  => '',
01522                         'speech'  => '',
01523                         'thesis' => 108,
01524                         'treaty'  => '',
01525                         'webpage' => 107,
01526       );
01527     }
01528     $vars = explode(' ', $types);
01529     foreach ($vars as $key => $value) {
01530       $vars[$key] = (!empty($this->type_map[$value])) ? $this->type_map[$value] : '';
01531     }
01532 
01533     return implode(' ', $vars);
01534 
01535   }
01536 
01537 }
01538 //$csl_data = simplexml_load_file('./style/chicago-fullnote-bibliography.csl');
01539  //     $local_xml = simplexml_load_file('./locale/locales-en-US.xml');
01540 $csl_data ='./style/chicago-fullnote-bibliography.csl';
01541 $csl_data = file_get_contents($csl_data);
01542 $test_data = file_get_contents("./tests/fullstyles_ChicagoNoteWithBibliographyWithPublisher.json");
01543 $test_data = json_decode($test_data);
01544 
01545 $citeproc = new citeproc($csl_data);
01546 $input_data  = (array)$test_data->input;
01547 $count =  count($input_data);
01548 foreach($input_data as $data) {
01549  print $citeproc->render($data).'<br>';
01550 }
01551 //print $text;
01552 //print($csl_parse);
 All Data Structures Files Functions Variables