Added templates
[bibliodb.git] / CiteFields.php
bloba4ac4c9b81e614a352cf08aebab3a709936221a2
1 <?php
2 class CSL{
3 //Subnodes
4 private $info=null;
5 private $macros=array();
6 private $locale=null;
7 private $citation=null;
8 private $bibliography=null;
9 private $name="";
10 private $lang="en";
11 private $types=array();
12 final private function __clone() {}
13 final private function __construct() {
14 $this->addFilter("base","CiteprocField");
15 $this->addFilter("names","CiteprocNames");
16 $this->addFilter("text","CSLText");
17 $this->addFilter("number","CSLNumber");
18 $this->addFilter("group","CSLGroup");
19 $this->addFilter("choose","CSLChoose");
20 $this->citation=new CSLCitation($this);
21 $this->bibliography=new CSLBibliography($this);
25 final private static function getInstance()
27 static $instance = null;
28 if (null === $instance) {
29 $instance = new self();
31 return $instance;
34 public function style($name){
35 $instance=self::getInstance();
36 $instance->name=$name;
37 return $instance;
39 public function citation(){
40 $instance=self::getInstance();
41 return $instance->citation;
43 public function bibliography(){
44 $instance=self::getInstance();
45 return $instance->bibliography;
48 public function macro($macro_name){
49 $instance=self::getInstance();
50 $macro=new CSLMacro($instance);
51 $instance->macros[$macro_name]=$macro;
52 return $macro;
54 public function useMacro($macro_name=""){
55 $instance=self::getInstance();
56 if(array_key_exists($macro_name,$instance->macros))
57 return $instance->macros[$macro_name]->get();
58 return false;
60 public function lang($lang){
61 $instance=self::getInstance();
62 $instance->lang=$lang;
63 return $instance;
65 public function useTerm($term, $lang){
66 $instance=self::getInstance();
67 $lang=$lang?$lang:$instance->lang;
68 return "$term-$lang";
70 public function cite(){
71 //ToDo: Generate citekey
72 $instance=self::getInstance();
73 return $instance->citation->get();
75 public function printBibliography($records=false){
76 $instance=self::getInstance();
77 CiteData::records($records);
78 $out=CiteOutput::factory()->noEscape()->template("bibstart");
79 while(CiteData::current()===true){
80 $cite=$instance->cite();
81 $bib=$instance->getBibRecord();
82 $out->text($instance->formatBibRecord($cite,$bib));
83 CiteData::next();
84 Profiller::speed("Položka bibliografie");
86 $out->template("bibend");
87 $out->out();
88 return $this;
90 public function formatBibRecord($citation, $record){
91 return CiteOutput::factory()->noEscape()->text("$record")->template("@bibliography/entry")->get();
93 public function getBibRecord(){
94 $instance=self::getInstance();
95 return $instance->bibliography->get();
96 //$out=CiteOutput::factory()->noEscape();
97 //foreach($instance->fields as $field){
98 // $out->text($field->get());
99 // }
100 //return $out->get();
102 public function field($type){
103 $instance=self::getInstance();
104 if(array_key_exists($type,$instance->types)){
105 $c=new $instance->types[$type]($instance);
106 $instance->fields[]=$c;
107 return $c;
108 }else{
109 throw new Exception("Output filter \"$type\" doesn´t exist");
113 public function getField($type,$parent){
114 $instance=self::getInstance();
115 if(array_key_exists($type,$instance->types)){
116 $c=new $instance->types[$type]($parent);
117 //$instance->fields[]=$c;
118 return $c;
119 }else{
120 throw new Exception("Output filter \"$type\" doesn´t exist");
123 function addFilter($name,$class){
124 $this->types[$name]=$class;
128 class CSLBase{
129 public $data=null;
130 protected $value=null;
131 protected $fields=array();
132 protected $parent_class=null;
133 public $variable=null;
134 protected $delimiter=",";
135 protected $actions=array();
136 protected $form=null;
137 protected $term=null;
138 protected $lang=null;
139 public $macro=null;
140 function __construct($parent){
141 $this->parent_class=$parent;
143 public function setData($data){
144 $this->data=$data;
145 return $this;
147 public function setter($variable,$value){
148 $this->$variable=$value;
149 return $this;
151 public function variable($name){
152 $this->variable=$name;
153 return $this;
155 public function macro($macro_name){
156 $this->macro=$macro_name;
157 return $this;
159 public function term($term_name,$lang=false){
160 //$lang = language of cited document
161 $this->term=$term_name;
162 $this->lang=$lang;
163 return $this;
165 public function value($value){
166 $this->value=$value;
167 return $this;
169 public function form($form="long"){
170 //form = long / short / verb / verb-short / symbol
171 $this->form =$form;
172 return $this;
174 protected function getData($field=null){
175 if($field!=null){
176 return CiteData::getList($field);
177 }else if($this->macro!=null){
178 //echo "Použiju makro<br />";
179 return CSL::useMacro($this->macro);
180 }else if($this->data){
181 return $this->useFormat($this->data);
182 }else if($this->value){
183 return $this->value;
184 }else if($this->term){
185 return CSL::useTerm($this->term, $this->lang);
186 }else{
187 echo "Nic z toho<br />";
188 return "";
191 public function end(){
192 //print_r($this->parent_class);
193 return $this->parent_class;
195 protected function useFormat($data){
196 return implode($this->delimiter,$data);
198 public function field($type){
199 $c=CSL::getField($type,$this);
200 $this->fields[]=$c;
201 return $c;
206 class CSLTop extends CiteprocField{
207 protected $sort=null;
208 protected $layout=null;
209 public function __construct($parent){
210 parent::__construct($parent);
211 $this->sort=new CSLSort($this);
212 $this->layout=new CSLLayout($this);
214 public function sort(){return $this->sort;}
215 public function layout(){return $this->layout;}
216 public function get(){return $this->layout->get();}
217 public function getSortOptions(){$this->sort->get();}
220 class CSLCitation extends CSLTop{
221 public function get(){
222 $author=array_shift($this->getData("author"));
223 $author=$author["family"].", ".$author["given"];
224 $year=$this->getData("date");
225 $key=CiteData::getCiteKey();
226 return "[$author($year)]{{$key}}";
230 class CSLBibliography extends CSLTop{
231 public function get(){
232 return $this->layout->get();
235 class CSLSort extends CiteprocField{
236 public function get(){
237 return $this->layout->get();
240 class CSLSubFields extends CiteprocField{
241 public function get(){
242 $out=CiteOutput::factory()->noEscape();
243 foreach($this->fields as $field){
244 $out->text($field->get());
246 return $out->get();
249 class CSLLayout extends CSLSubFields{
251 class CiteprocField extends CSLBase{
252 public $prefix="";
253 public $suffix="";
254 //public $macros=array();
255 //public $data;
256 protected $font_style=array("normal"=>"@font-style/normal","italic"=>"@font-style/italic","oblique"=>"@font-style/oblique");
257 protected $font_variant=array("normal"=>"@font-variant/normal","small-caps"=>"@font-variant/small-caps");
258 protected $font_weight=array("normal"=>"@font-weight/normal","bold"=>"@font-weight/bold","light"=>"@font-weight/light");
259 protected $text_decoration=array("none"=>"@text-decoration/none","underline"=>"@text-decoration/underline");
260 protected $vertical_align=array("baseline"=>"@vertical-align/baseline","sup"=>"@vertical-align/sup","sub"=>"@vertical-align/sub");
261 protected $styles=array();
263 protected $text_case="";
265 public function __construct($parent){
266 parent::__construct($parent);
267 $this->prefix($this->parent_class->prefix)
268 ->suffix($this->parent_class->suffix);
271 public function prefix($s){
272 $this->prefix=$s;
273 return $this;
275 public function suffix($s){
276 $this->suffix=$s;
277 return $this;
279 //style functions
280 public function fontStyle($style){return $this->style($this->font_style,$style);}
281 public function fontVariant($style){return $this->style($this->font_variant,$style);}
282 public function fontWeight($style){return $this->style($this->font_weight,$style);}
283 public function textDecoration($style){return $this->style($this->text_decoration,$style);}
284 public function verticalAlign($style){return $this->style($this->vertical_align,$style);}
285 public function style($stylearray,$style){
286 if(array_key_exists($style, $stylearray)){
287 $this->styles[]=$stylearray[$style];
289 return $this;
291 public function textCase($case){$this->text_case=$case;return $this;}
293 protected function useStyle($s){
294 $format=CiteOutput::factory($s)->textFunction($this->text_case);
295 foreach($this->styles as $style)$format->template($style);
296 return $format->get();
298 //protected function getData(){
299 // return CiteData::getField($this->variable);
301 protected function usePrefix(){return $this->prefix;}
302 protected function useSuffix($s=null){
303 $last_char=substr(trim($s),-1);
304 return ($last_char==$this->suffix)?"":$this->suffix;
306 public function get(){
307 $data= $this->getData($this->variable);
308 if($data){
309 return $this->usePrefix().$this->useStyle($data).$this->useSuffix($data);
310 }else{
311 return false;
315 public function printError(Exception $e){
316 echo "<div style=\"border:1px solid black;color:red;\">".error_message.$e->getMessage()."</div>\n";
320 class CiteprocList extends CiteprocField{
321 protected $limit=false;
322 protected $limit_use=false;
324 public function limit($limit){
325 $this->limit=$limit;
326 return $this;
328 public function limitUse($use){
329 $this->limit_use=$use;
330 return $this;
332 protected function processField($field,$last=false){
333 return implode(", ",$field);
335 public function get(){
336 try{
337 $data=CiteData::getList($this->variable);
338 $data_len=count($data);
339 if($data_len==0)return false;
340 $max=$this->limit_use?$this->limit_use:$this->limit;
341 $counter=$this->limit?$this->limit:$data_len;
342 $counter=($counter >= $data_len)?$data_len:$max;
343 $return_value=$this->usePrefix();
344 //CiteOutput::factory("Použijeme $counter položek. Maximum je $max, $položek v databázi bylo $data_len")->out();
345 $fields=array();
346 for($i=0;$i<$counter;$i++){
347 //$return_value.=$this->processField($data[$i]);
348 $last=($i==($counter-2))?1:0;
349 $last=($i==($counter-1))?-1:$last;
350 $return_value.=$this->processField($data[$i],$last);
352 //if(count($fields)>1){
353 // $delim=array_slice($fields,0,count($fields)-1);
354 // $last=array_slice($fields,-1);
355 // $return_value.=implode($this->useDelimiter(),$delim).$this->use
357 $return_value.=$this->useSuffix($return_value);
358 return $return_value;
359 //CiteOutput::factory("Použijeme $counter položek. Maximum je $max, $položek v databázi bylo $data_len")->out();
362 catch(Exception $e){
363 CiteOutput::factory("There is some problem with data: ".$e->getMessage())->out();;
370 class CiteprocDataSet extends CiteprocField{
371 public $data=null;
372 public function setData($data){
373 $this->data=$data;
374 return $this;
376 protected function getData($variable=null){
377 return $this->useFormat($this->data);
381 //CitationStyle Names element
382 class CiteprocNames extends CiteprocList{
384 public $suffix=".";
385 protected $names=null;
386 public function __construct($parent){
387 parent::__construct($parent);
388 $this->names=new CiteprocName($this);
390 protected function processField($data,$last=false){
391 $this->names->setData($data);
392 $add="";
393 if($last==0){
394 $add=$this->names->useDelimiter();
395 }else if($last>0){
396 $add=$this->names->useDelimiterPrecedesLast();
398 //CiteOutput::factory("Oddělovač $add")->lineBreak()->out();
399 return "{$this->names->get()}$add";
401 public function name(){
402 return $this->names;
406 class CiteprocName extends CiteprocDataSet{
407 //Musí být zabalen ve třídě CiterpocNames
409 private $parts=array();
410 protected $delimiter=",";
411 protected $_and=" & ";
412 protected $precedes_last="never";
414 public function useDelimiter(){ return $this->delimiter;}
415 public function useAnd(){return $this->_and;}
416 public function useDelimiterPrecedesLast(){
417 switch($this->precedes_last){
418 case "always":
419 return $this->delimiter.$this->_and;
420 break;
421 default:
422 return $this->_and;
426 public function namePart($part_name){
427 $this->parts[$part_name]=new CiteprocNamePart($this);
428 return $this->parts[$part_name];
430 public function delimiter($s){
431 $this->delimiter=$s;
432 return $this;
434 public function delimiterAnd($s){
435 $this->_and=$s;
436 return $this;
438 protected function usePart($part,$data){
439 if(array_key_exists($part,$data)){
440 if(array_key_exists($part,$this->parts)){
441 return $this->parts[$part]->setData($data)
442 ->variable($part)
443 ->get();
444 //return $this->parts[$part]->get();
445 }else{
446 return $data[$part];
448 }else{
449 return $part;
452 protected function useFormat($part){
453 $parts=array("family",", ","given");
454 $return_value ="";
455 foreach($parts as $element){
456 $return_value.=$this->usePart($element,$part);
458 return $return_value;
459 //return implode(", ",array($part[family],$part["given"]));
461 //public function get(){
462 // return $this->usePrefix().$this->useStyle($this->getData()).$this->useSuffix();
465 class CiteprocNamePart extends CiteprocDataSet{
466 public function getData($variable){
467 return $this->data[$variable];
472 class CSLMacro extends CSLSubFields{}
473 class CSLText extends CiteprocField{
475 class CSLNumber extends CiteprocField{}
476 class CSLGroup extends CSLSubFields{
477 public function get(){
478 $out=CiteOutput::factory()->noEscape();
479 $condition=false;
480 $checked_values=0;
481 //$out->text();
482 foreach($this->fields as $field){
483 $result=$field->get();
484 if($field->variable OR $field->macro){
485 $sub_condition=strlen($result)>0?true:false;
486 $condition=($condition || $sub_condition);
487 $checked_values++;
489 $out->text($result);
491 //$out->text($this->useSuffix());
492 if($condition===false AND $checked_values>0){
493 return false;
494 } else{
495 return $this->usePrefix().$this->useStyle($out->get()).$this->useSuffix();
500 class CSLChoose extends CiteprocField{
501 protected $ifs=array();
502 protected $elses=null;
503 public function cslIf(){
504 $if= new CSLIf($this);
505 $this->ifs[]= $if;
506 return $if;
508 public function cslElseIf(){
509 return $this->cslIf();
511 public function cslElse(){
512 $else=new CSLIf($this);
513 $this->elses=$else;
514 return $else;
516 public function get(){
517 $pruchod=0;
518 $trues=array();
519 foreach($this->ifs as $condition){
520 $pruchod++;
521 $result=$condition->get();
522 //CiteOutput::factory("Tak a result je $result, průchod $pruchod")->lineBreak()->out();
523 if(strlen($result)>0){
524 $trues[]=array("disambiguate"=>$condition->getDisambiguate(),"content"=>$result);
527 //CiteOutput::factory("Tak a result je $result, průchod $pruchod")->lineBreak()->out();
528 if(count($trues)>0){
529 foreach($trues as $disambig){
530 if($disambig["disambiguate"])return $disambig["content"];
532 return $trues[0]["content"];
534 if($this->elses)return $this->elses->get();
535 return false;
539 class CSLIf extends CSLSubFields{
540 protected $disambiguate=false;
541 protected $conditions=array();
542 protected $matches="all";
543 protected function setCondition($condition_name,$values){
544 $chunks=explode(" ",$values);
545 $this->conditions[$condition_name]=$chunks;
546 return $this;
548 //public function cslIf(){return $this->parent_class->cslIf();}
549 public function cslElseIf(){ return $this->parent_class->cslElseIf();}
550 public function cslElse(){return $this->parent_class->cslElse();}
551 public function getDisambiguate(){
552 return $this->disambiguate;
554 //conditional functions
555 public function disambiguate($disambiguate=true){
556 $this->disambiguate=$disambiguate;
557 return $this;
559 public function isNumeric($variable){return $this->setCondition("IsNumeric",$variable);}
560 public function isUncertainDate($variable){return $this->setCondition("IsUncertain_date",$variable);}
561 public function locator($variable){return $this->setCondition("Locator",$variable);}
562 public function position($variable){
563 //Implementovat v budoucnu, zatím nemá smysl
564 return $this;
567 public function type($type){return $this->setCondition("Type",$type);}
569 public function variable($variable){return $this->setCondition("Variable",$variable);}
571 public function match($match="all"){return $this->setter("matches",$match);}
573 protected function testIsNumeric($variable){return is_numeric(CiteData::getData($variable));}
574 protected function testIsUncertainDate($variable){return false;}
575 protected function testLoacator($variable){return CiteData::getData("locator")==$variable;}
576 protected function testPosition($position){return false;}
577 protected function testType($type){return CiteData::getData("type")==$type;}
578 protected function testVariable($variable){return CiteData::getData($variable)!==null;}
579 protected function logical($conditions){
580 if(count($conditions)==1)return $conditions[0];
581 $sum=$this->matches=="all"?true:false;
582 foreach($conditions as $cond){
583 $suma=$cond?"true":"false";
584 if($this->matches=="any"){
585 $sum=($sum OR $cond);
586 }else{
587 $sum=($sum AND $cond);
590 return $this->matches=="none"?!$sum:$sum;
593 protected function testCondition($condition_name,$values){
594 $conditions=array();
595 $condition_method="test$condition_name";
596 foreach($values as $element){
597 $conditions[]=$this->$condition_method($element);
599 return $this->logical($conditions);
602 public function get(){
603 $condition=array();
604 foreach($this->conditions as $sub_condition=>$values){
605 $condition[]=$this->testCondition($sub_condition,$values);
607 //CiteOutput::factory(implode(" - ",$condition))->lineBreak()->out();
608 if($this->logical($condition))return parent::get();
609 if(!count($this->conditions)>0)return parent::get();
610 return false;