ILIAS  Release_5_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilObjBibliographic.php
Go to the documentation of this file.
1 <?php
2 
3 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
4 require_once "Services/Object/classes/class.ilObject2.php";
5 require_once "Modules/Bibliographic/classes/class.ilBibliographicEntry.php";
6 /* Declaring namespace for library RISReader */
7 use \LibRIS\RISReader;
8 
18 
30  protected $filename;
36  protected $entries;
42  protected $overviewModels;
48  protected $is_online;
49 
50 
56  public function initType() {
57  $this->type = "bibl";
58  }
59 
60 
68  public function __construct($existant_bibl_id = 0) {
69  if ($existant_bibl_id) {
70  $this->setId($existant_bibl_id);
71  $this->doRead();
72  }
73  parent::__construct($existant_bibl_id, false);
74  }
75 
76 
82  protected function doCreate() {
83  global $ilDB;
84  $ilDB->manipulate("INSERT INTO il_bibl_data " . "(id, filename, is_online) VALUES (" . $ilDB->quote($this->getId(), "integer") . "," . // id
85  $ilDB->quote($this->getFilename(), "text") . "," . // filename
86  $ilDB->quote($this->getOnline(), "integer") . // is_online
87  ")");
88  }
89 
90 
91  protected function doRead() {
92  global $ilDB;
93  $set = $ilDB->query("SELECT * FROM il_bibl_data " . " WHERE id = " . $ilDB->quote($this->getId(), "integer"));
94  while ($rec = $ilDB->fetchAssoc($set)) {
95  if (! $this->getFilename()) {
96  $this->setFilename($rec["filename"]);
97  }
98  $this->setOnline($rec['is_online']);
99  }
100  }
101 
102 
106  public function doUpdate() {
107  global $ilDB;
108  if (! empty($_FILES['bibliographic_file']['name'])) {
109  $this->deleteFile();
110  $this->moveFile();
111  }
112  // Delete the object, but leave the db table 'il_bibl_data' for being able to update it using WHERE, and also leave the file
113  $this->doDelete(true, true);
114  $ilDB->manipulate("UPDATE il_bibl_data SET " . "filename = " . $ilDB->quote($this->getFilename(), "text") . ", " . // filename
115  "is_online = " . $ilDB->quote($this->getOnline(), "integer") . // is_online
116  " WHERE id = " . $ilDB->quote($this->getId(), "integer"));
117  $this->writeSourcefileEntriesToDb($this);
118  }
119 
120 
125  protected function doDelete($leave_out_il_bibl_data = false, $leave_out_delete_file = false) {
126  global $ilDB;
127  if (! $leave_out_delete_file) {
128  $this->deleteFile();
129  }
130  //il_bibl_attribute
131  $ilDB->manipulate("DELETE FROM il_bibl_attribute WHERE il_bibl_attribute.entry_id IN "
132  . "(SELECT il_bibl_entry.id FROM il_bibl_entry WHERE il_bibl_entry.data_id = " . $ilDB->quote($this->getId(), "integer") . ");");
133  //il_bibl_entry
134  $ilDB->manipulate("DELETE FROM il_bibl_entry WHERE data_id = " . $ilDB->quote($this->getId(), "integer"));
135  if (! $leave_out_il_bibl_data) {
136  //il_bibl_data
137  $ilDB->manipulate("DELETE FROM il_bibl_data WHERE id = " . $ilDB->quote($this->getId(), "integer"));
138  }
139  // delete history entries
140  require_once("./Services/History/classes/class.ilHistory.php");
142  }
143 
144 
148  public function getFileDirectory() {
149  return ilUtil::getDataDir() . DIRECTORY_SEPARATOR . $this->getType() . DIRECTORY_SEPARATOR . $this->getId();
150  }
151 
152 
158  public function moveFile($file_to_copy = false) {
159  $target_dir = $this->getFileDirectory();
160  if (! is_dir($target_dir)) {
161  ilUtil::makeDirParents($target_dir);
162  }
163  if ($_FILES['bibliographic_file']['name']) {
164  $filename = $_FILES['bibliographic_file']['name'];
165  } elseif ($file_to_copy) {
166  //file is not uploaded, but a clone is made out of another bibl
167  $split_path = explode(DIRECTORY_SEPARATOR, $file_to_copy);
168  $filename = $split_path[sizeof($split_path) - 1];
169  } else {
170  throw new Exception("Either a file must be delivered via \$_POST/\$_FILE or the file must be delivered via the method argument file_to_copy");
171  }
172  $target_full_filename = $target_dir . DIRECTORY_SEPARATOR . $filename;
173  //If there is no file_to_copy (which is used for clones), copy the file from the temporary upload directory (new creation of object).
174  //Therefore, a warning predicates nothing and can be suppressed.
175  if (@! copy($file_to_copy, $target_full_filename)) {
176  if (! empty($_FILES['bibliographic_file']['tmp_name'])) {
177  ilUtil::moveUploadedFile($_FILES['bibliographic_file']['tmp_name'], $_FILES['bibliographic_file']['name'], $target_full_filename);
178  } else {
179  throw new Exception("The file delivered via the method argument file_to_copy could not be copied. The file '{$file_to_copy}' does probably not exist.");
180  }
181  }
182  $this->setFilename($filename);
183  ilUtil::sendSuccess($this->lng->txt("object_added"), true);
184  }
185 
186 
187  function deleteFile() {
188  $path = $this->getFilePath(true);
190  }
191 
192 
198  public function getFilePath($without_filename = false) {
199  global $ilDB;
200  $set = $ilDB->query("SELECT filename FROM il_bibl_data " . " WHERE id = " . $ilDB->quote($this->getId(), "integer"));
201  $rec = $ilDB->fetchAssoc($set);
202  {
203  if ($without_filename) {
204  return substr($rec['filename'], 0, strrpos($rec['filename'], DIRECTORY_SEPARATOR));
205  } else {
206  return $rec['filename'];
207  }
208  }
209  }
210 
211 
215  public function setFilename($filename) {
216  $this->filename = $filename;
217  }
218 
219 
223  public function getFilename() {
224  return $this->filename;
225  }
226 
227 
231  public function getFileAbsolutePath() {
232  return $this->getFileDirectory() . DIRECTORY_SEPARATOR . $this->getFilename();
233  }
234 
235 
236  public function getFiletype() {
237  //return bib for filetype .bibtex:
238  if (strtolower(substr($this->getFilename(), - 6)) == "bibtex") {
239  return "bib";
240  }
241 
242  //else return its true filetype
243  return strtolower(substr($this->getFilename(), - 3));
244  }
245 
246 
250  public static function getAllOverviewModels() {
251  global $ilDB;
252  $overviewModels = array();
253  $set = $ilDB->query('SELECT * FROM il_bibl_overview_model');
254  while ($rec = $ilDB->fetchAssoc($set)) {
255  if ($rec['literature_type']) {
256  $overviewModels[$rec['filetype']][$rec['literature_type']] = $rec['pattern'];
257  } else {
258  $overviewModels[$rec['filetype']] = $rec['pattern'];
259  }
260  }
261 
262  return $overviewModels;
263  }
264 
265 
273  protected static function __force_rmdir($path) {
274  if (! file_exists($path)) {
275  return false;
276  }
277  if (is_file($path) || is_link($path)) {
278  return unlink($path);
279  }
280  if (is_dir($path)) {
281  $path = rtrim($path, DIRECTORY_SEPARATOR) . DIRECTORY_SEPARATOR;
282  $result = true;
283  $dir = new DirectoryIterator($path);
284  foreach ($dir as $file) {
285  if (! $file->isDot()) {
286  $result &= self::__force_rmdir($path . $file->getFilename(), false);
287  }
288  }
289  $result &= rmdir($path);
290 
291  return $result;
292  }
293  }
294 
295 
302  public static function __readRisFile($full_filename) {
303  self::__setCharsetToUtf8($full_filename);
304  require_once "./Modules/Bibliographic/lib/LibRIS/src/LibRIS/RISReader.php";
305  $ris_reader = new RISReader();
306  $ris_reader->parseFile($full_filename);
307 
308  return $ris_reader->getRecords();
309  }
310 
311 
317  public static function __readBibFile($full_filename) {
318  self::__setCharsetToUtf8($full_filename);
319  require_once 'Modules/Bibliographic/lib/PEAR_BibTex_1.0.0RC5/Structures/BibTex.php';
320  $bibtex_reader = new Structures_BibTex();
321  //Loading and parsing the file example.bib
322  $bibtex_reader->loadFile($full_filename);
323  //replace bibtex special chars with the real characters
324  $bibtex_reader->content = self::__convertBibSpecialChars($bibtex_reader->content);
325  $bibtex_reader->setOption('extractAuthor', false);
326  $bibtex_reader->parse();
327  // Remove library-bug: if there is no cite, the library mixes up the key for the type and the first attribute.
328  // It also shows an empty and therefore unwanted cite in the array.
329  //
330  // The cite is the text coming right after the type. Example:
331  // @book {cite,
332  // author = { "...."},
333  foreach ($bibtex_reader->data as $key => $entry) {
334  if (empty($entry['cite'])) {
335  unset($bibtex_reader->data[$key]['cite']);
336  foreach ($entry as $attr_key => $attribute) {
337  if (strpos($attr_key, '{') !== false) {
338  unset($bibtex_reader->data[$key][$attr_key]);
339  $attr_key_exploaded = explode('{', $attr_key);
340  $bibtex_reader->data[$key]['entryType'] = trim($attr_key_exploaded[0]);
341  $bibtex_reader->data[$key][trim($attr_key_exploaded[1])] = $attribute;
342  }
343  }
344  }
345  // formating the author to the following type of string
346  // Smith, John / Comte, Gabriel / von Gunten Jr, Thomas
347  foreach ($entry as $attr_key => $attribute) {
348  if ($attr_key == 'author' && is_array($attribute)) {
349  $attribute_string = array();
350  foreach ($attribute as $author_key => $author) {
351  $lastname = array( $author['von'], $author['last'], $author['jr'] );
352  $attribute_string[$author_key] = implode(' ', array_filter($lastname));
353  if (! empty($author['first'])) {
354  $attribute_string[$author_key] .= ', ' . $author['first'];
355  }
356  }
357  $bibtex_reader->data[$key][$attr_key] = implode(' / ', $attribute_string);
358  }
359  }
360  }
361 
362  return $bibtex_reader->data;
363  }
364 
365 
369  public static function __setCharsetToUtf8($full_filename) {
370  //If file charset does not seem to be Unicode, we assume that it is ISO-8859-1, and convert it to UTF-8.
371  $filedata = file_get_contents($full_filename);
372  if (strlen($filedata) == strlen(utf8_decode($filedata))) {
373  // file charset is not UTF-8
374  $filedata = mb_convert_encoding($filedata, 'UTF-8', 'ISO-8859-1');
375  file_put_contents($full_filename, $filedata);
376  }
377  }
378 
379 
388  public static function __convertBibSpecialChars($file_content) {
389  $bibtex_special_chars['ä'] = '{\"a}';
390  $bibtex_special_chars['ë'] = '{\"e}';
391  $bibtex_special_chars['ï'] = '{\"i}';
392  $bibtex_special_chars['ö'] = '{\"o}';
393  $bibtex_special_chars['ü'] = '{\"u}';
394  $bibtex_special_chars['Ä'] = '{\"A}';
395  $bibtex_special_chars['Ë'] = '{\"E}';
396  $bibtex_special_chars['Ï'] = '{\"I}';
397  $bibtex_special_chars['Ö'] = '{\"O}';
398  $bibtex_special_chars['Ü'] = '{\"U}';
399  $bibtex_special_chars['â'] = '{\^a}';
400  $bibtex_special_chars['ê'] = '{\^e}';
401  $bibtex_special_chars['î'] = '{\^i}';
402  $bibtex_special_chars['ô'] = '{\^o}';
403  $bibtex_special_chars['û'] = '{\^u}';
404  $bibtex_special_chars['Â'] = '{\^A}';
405  $bibtex_special_chars['Ê'] = '{\^E}';
406  $bibtex_special_chars['Î'] = '{\^I}';
407  $bibtex_special_chars['Ô'] = '{\^O}';
408  $bibtex_special_chars['Û'] = '{\^U}';
409  $bibtex_special_chars['à'] = '{\`a}';
410  $bibtex_special_chars['è'] = '{\`e}';
411  $bibtex_special_chars['ì'] = '{\`i}';
412  $bibtex_special_chars['ò'] = '{\`o}';
413  $bibtex_special_chars['ù'] = '{\`u}';
414  $bibtex_special_chars['À'] = '{\`A}';
415  $bibtex_special_chars['È'] = '{\`E}';
416  $bibtex_special_chars['Ì'] = '{\`I}';
417  $bibtex_special_chars['Ò'] = '{\`O}';
418  $bibtex_special_chars['Ù'] = '{\`U}';
419  $bibtex_special_chars['á'] = '{\\\'a}';
420  $bibtex_special_chars['é'] = '{\\\'e}';
421  $bibtex_special_chars['í'] = '{\\\'i}';
422  $bibtex_special_chars['ó'] = '{\\\'o}';
423  $bibtex_special_chars['ú'] = '{\\\'u}';
424  $bibtex_special_chars['Á'] = '{\\\'A}';
425  $bibtex_special_chars['É'] = '{\\\'E}';
426  $bibtex_special_chars['Í'] = '{\\\'I}';
427  $bibtex_special_chars['Ó'] = '{\\\'O}';
428  $bibtex_special_chars['Ú'] = '{\\\'U}';
429  $bibtex_special_chars['à'] = '{\`a}';
430  $bibtex_special_chars['è'] = '{\`e}';
431  $bibtex_special_chars['ì'] = '{\`i}';
432  $bibtex_special_chars['ò'] = '{\`o}';
433  $bibtex_special_chars['ù'] = '{\`u}';
434  $bibtex_special_chars['À'] = '{\`A}';
435  $bibtex_special_chars['È'] = '{\`E}';
436  $bibtex_special_chars['Ì'] = '{\`I}';
437  $bibtex_special_chars['Ò'] = '{\`O}';
438  $bibtex_special_chars['Ù'] = '{\`U}';
439  $bibtex_special_chars['ç'] = '{\c c}';
440  $bibtex_special_chars['ß'] = '{\ss}';
441  $bibtex_special_chars['ñ'] = '{\~n}';
442  $bibtex_special_chars['Ñ'] = '{\~N}';
443 
444  return str_replace($bibtex_special_chars, array_keys($bibtex_special_chars), $file_content);
445  }
446 
447 
458  public function doCloneObject(ilObjBibliographic $new_obj, $a_target_id, $a_copy_id = 0) {
459 
460  //copy online status if object is not the root copy object
461  $cp_options = ilCopyWizardOptions::_getInstance($a_copy_id);
462 
463  if(!$cp_options->isRootNode($this->getRefId()))
464  {
465  $new_obj->setOnline($this->getOnline());
466  }
467 
468  $new_obj->cloneStructure($this->getId());
469 
470  return $new_obj;
471  }
472 
473 
481  public function cloneStructure($original_id) {
482  $original = new ilObjBibliographic($original_id);
483  $this->moveFile($original->getFileAbsolutePath());
484  $this->setDescription($original->getDescription());
485  $this->setTitle($original->getTitle());
486  $this->setType($original->getType());
487  $this->doUpdate();
488  }
489 
490 
497  protected static function __removeSpacesAndDashesAtBeginning($input) {
498  for ($i = 0; $i < strlen($input); $i ++) {
499  if ($input[$i] != " " && $input[$i] != "-") {
500  return substr($input, $i);
501  }
502  }
503  }
504 
505 
511  public function writeSourcefileEntriesToDb() {
512  //Read File
513  $entries_from_file = array();
514  switch ($this->getFiletype()) {
515  case("ris"):
516  $entries_from_file = self::__readRisFile($this->getFileAbsolutePath());
517  break;
518  case("bib"):
519  $entries_from_file = self::__readBibFile($this->getFileAbsolutePath());
520  break;
521  }
522  //fill each entry into a ilBibliographicEntry object and then write it to DB by executing doCreate()
523  foreach ($entries_from_file as $file_entry) {
524  $type = NULL;
525  $x = 0;
526  $parsed_entry = array();
527  foreach ($file_entry as $key => $attribute) {
528  // if the attribute is an array, make a comma separated string out of it
529  if (is_array($attribute)) {
530  $attribute = implode(", ", $attribute);
531  }
532  // reduce the attribute strings to a maximum of 4000 (ATTRIBUTE_VALUE_MAXIMAL_TEXT_LENGTH) characters, in order to fit in the database
533  //if (mb_strlen($attribute, 'UTF-8') > self::ATTRIBUTE_VALUE_MAXIMAL_TEXT_LENGTH) {
534  if (ilStr::strLen($attribute) > self::ATTRIBUTE_VALUE_MAXIMAL_TEXT_LENGTH) {
535  // $attribute = mb_substr($attribute, 0, self::ATTRIBUTE_VALUE_MAXIMAL_TEXT_LENGTH - 3, 'UTF-8') . '...';
536  $attribute = ilStr::subStr($attribute, 0, self::ATTRIBUTE_VALUE_MAXIMAL_TEXT_LENGTH - 3) . '...';
537  }
538  // ty (RIS) or entryType (BIB) is the type and is treated seperately
539  if (strtolower($key) == 'ty' || strtolower($key) == 'entrytype') {
540  $type = $attribute;
541  continue;
542  }
543  //TODO - Refactoring for ILIAS 4.5 - get rid off array restructuring
544  //change array structure (name not as the key, but under the key "name")
545  $parsed_entry[$x]['name'] = $key;
546  $parsed_entry[$x ++]['value'] = $attribute;
547  }
548  //create the entry and fill data into database by executing doCreate()
549  $entry_model = ilBibliographicEntry::getInstance($this->getFiletype());
550  $entry_model->setType($type);
551  $entry_model->setAttributes($parsed_entry);
552  $entry_model->setBibliographicObjId($this->getId());
553  $entry_model->doCreate();
554  }
555  }
556 
557 
561  public function setOnline($a_online) {
562  $this->is_online = $a_online;
563  }
564 
565 
569  public function getOnline() {
570  return $this->is_online;
571  }
572 }