ILIAS  release_7 Revision v7.30-3-g800a261c036
All Data Structures Namespaces Files Functions Variables Modules Pages
class.ilAdvancedMDRecordParser.php
Go to the documentation of this file.
1 <?php
2 /*
3  +-----------------------------------------------------------------------------+
4  | ILIAS open source |
5  +-----------------------------------------------------------------------------+
6  | Copyright (c) 1998-2006 ILIAS open source, University of Cologne |
7  | |
8  | This program is free software; you can redistribute it and/or |
9  | modify it under the terms of the GNU General Public License |
10  | as published by the Free Software Foundation; either version 2 |
11  | of the License, or (at your option) any later version. |
12  | |
13  | This program is distributed in the hope that it will be useful, |
14  | but WITHOUT ANY WARRANTY; without even the implied warranty of |
15  | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
16  | GNU General Public License for more details. |
17  | |
18  | You should have received a copy of the GNU General Public License |
19  | along with this program; if not, write to the Free Software |
20  | Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
21  +-----------------------------------------------------------------------------+
22 */
23 
34 include_once('Services/AdvancedMetaData/classes/class.ilAdvancedMDRecord.php');
35 include_once('Services/AdvancedMetaData/classes/class.ilAdvancedMDFieldDefinition.php');
36 
38 {
39  const MODE_UPDATE = 1;
40  const MODE_INSERT = 2;
43 
44  private $mode;
45 
46  private $fields = array();
47 
48  private $is_error = false;
49  private $error_msg = array();
50 
51  protected $context; // [array]
52 
53  protected $scopes = [];
54 
55  protected $translations = [];
56  protected $translation_language = '';
57 
58  protected $field_translations = [];
60 
64  protected $log;
65 
73  public function __construct($a_file)
74  {
75  parent::__construct($a_file, true);
76  $this->log = ilLoggerFactory::getLogger('amet');
77  }
78 
86  public function setMode($a_mode)
87  {
88  $this->mode = $a_mode;
89  }
90 
97  public function getMode()
98  {
99  return $this->mode;
100  }
101 
102 
110  public function startParsing()
111  {
112  parent::startParsing();
113  if ($this->is_error) {
114  include_once('./Services/Xml/exceptions/class.ilSaxParserException.php');
115  throw new ilSaxParserException(implode('<br/>', $this->error_msg));
116  }
117  }
118 
125  public function setHandlers($a_xml_parser)
126  {
127  xml_set_object($a_xml_parser, $this);
128  xml_set_element_handler($a_xml_parser, 'handlerBeginTag', 'handlerEndTag');
129  xml_set_character_data_handler($a_xml_parser, 'handlerCharacterData');
130  }
131 
137  protected function handlerBeginTag($a_xml_parser, $a_name, $a_attribs)
138  {
139  switch ($a_name) {
140  case 'AdvancedMetaDataRecords':
141  $this->is_error = false;
142  $this->error_msg = array();
143  // Nothing to do
144  break;
145 
146  case 'Scope':
147  $this->scopes = [];
148  break;
149 
150  case 'ScopeEntry':
151  $parsed_id = ilUtil::parseImportId($a_attribs['id']);
152  if (
153  $parsed_id['inst_id'] == IL_INST_ID &&
154  ilObject::_exists($parsed_id['id'], true, $parsed_id['type'])
155  ) {
156  $scope = new ilAdvancedMDRecordScope();
157  $scope->setRefId($parsed_id['id']);
158  $this->scopes[] = $scope;
159  }
160  break;
161 
162 
163  case 'Record':
164  $this->fields = array();
165  $this->current_field = null;
166  $this->current_record = null;
167  if (!strlen($a_attribs['id']) or !isset($a_attribs['active'])) {
168  $this->appendErrorMessage('Missing XML attribute for element "Record".');
169  }
170  if (!$this->initRecordObject($a_attribs['id'])) {
171  $this->appendErrorMessage('Invalid attribute Id given for element "Record".');
172  }
173  $this->getCurrentRecord()->setActive($a_attribs['active']);
174  $this->getCurrentRecord()->setImportId($a_attribs['id']);
175  $this->getCurrentRecord()->setAssignedObjectTypes(array());
176 
177  if (isset($a_attribs['defaultLanguage'])) {
178  $language = (string) $a_attribs['defaultLanguage'];
179  if (ilLanguage::lookupId($language)) {
180  $this->getCurrentRecord()->setDefaultLanguage($language);
181  }
182  } else {
183  $this->getCurrentRecord()->setDefaultLanguage($this->lng->getDefaultLanguage());
184  }
185  break;
186 
187  case 'RecordTranslations':
188  $this->translations = [];
189  $this->field_translations = [];
190  $this->getCurrentRecord()->setDefaultLanguage(
191  $a_attribs['defaultLanguage'] ?? $this->getCurrentRecord()->getDefaultLanguage()
192  );
193  break;
194 
195  case 'RecordTranslation':
196  $this->translation_language = $a_attribs['language'] ?? $this->lng->getDefaultLanguage();
197  break;
198 
199  case 'FieldTranslations':
200  $this->field_translations[$this->getCurrentField()->getImportId()] = [];
201  break;
202 
203  case 'FieldTranslation':
204  $this->field_translation_language = $a_attribs['language'] ?? $this->lng->getDefaultLanguage();
205  break;
206 
207  case 'Title':
208  break;
209 
210  case 'Field':
211  if (!strlen($a_attribs['id']) or !isset($a_attribs['searchable']) or !isset($a_attribs['fieldType'])) {
212  $this->appendErrorMessage('Missing XML attribute for element "Field".');
213  }
214  if (!$this->initFieldObject($a_attribs['id'], $a_attribs['fieldType'])) {
215  $this->appendErrorMessage('Invalid attribute Id given for element "Record".');
216  }
217  $this->getCurrentField()->setImportId($a_attribs['id']);
218  $this->getCurrentField()->setSearchable($a_attribs['searchable'] == 'Yes' ? true : false);
219  break;
220 
221  case 'FieldTitle':
222  case 'FieldDescription':
223  case 'FieldPosition':
224  case 'FieldValue':
225  $this->field_value_id = $a_attribs['id'];
226  break;
227  }
228  }
229 
235  protected function handlerEndTag($a_xml_parser, $a_name)
236  {
237  switch ($a_name) {
238  case 'AdvancedMetaDataRecords':
239  break;
240 
241  case 'Record':
242  $this->storeRecords();
243  break;
244 
245  case 'Scope':
246  $this->getCurrentRecord()->setScopes($this->scopes);
247  break;
248 
249  case 'Title':
250  $this->getCurrentRecord()->setTitle(trim($this->cdata));
251  break;
252 
253  case 'Description':
254  $this->getCurrentRecord()->setDescription(trim($this->cdata));
255  break;
256 
257  case 'ObjectType':
258  // #12980
259  $parts = explode(":", trim($this->cdata));
260  $this->getCurrentRecord()->appendAssignedObjectType($parts[0], $parts[1]);
261  break;
262 
263  case 'Field':
264  break;
265 
266  case 'RecordTranslationTitle':
267  $this->translations[$this->translation_language]['title'] = trim($this->cdata);
268  break;
269 
270  case 'RecordTranslationDescription':
271  $this->translations[$this->translation_language]['description'] = trim($this->cdata);
272  break;
273 
274  case 'FieldTranslationTitle':
275  $this->field_translations[$this->getCurrentField()->getImportId()][$this->field_translation_language]['title'] = trim($this->cdata);
276  break;
277 
278  case 'FieldTranslationDescription':
279  $this->field_translations[$this->getCurrentField()->getImportId()][$this->field_translation_language]['description'] = trim($this->cdata);
280  break;
281 
282  case 'FieldTitle':
283  $this->getCurrentField()->setTitle(trim($this->cdata));
284  break;
285 
286  case 'FieldDescription':
287  $this->getCurrentField()->setDescription(trim($this->cdata));
288  break;
289 
290  case 'FieldPosition':
291  $this->getCurrentField()->setPosition((int) trim($this->cdata));
292  break;
293 
294  case 'FieldValue':
295  $this->getCurrentField()->importXMLProperty($this->field_value_id, trim($this->cdata));
296  break;
297  }
298  $this->cdata = '';
299  }
300 
307  protected function handlerCharacterData($a_xml_parser, $a_data)
308  {
309  if ($a_data != "\n") {
310  // Replace multiple tabs with one space
311  $a_data = preg_replace("/\t+/", " ", $a_data);
312 
313  $this->cdata .= $a_data;
314  }
315  }
316 
324  private function initRecordObject($a_id)
325  {
326  switch ($this->getMode()) {
327  case self::MODE_INSERT:
328  case self::MODE_INSERT_VALIDATION:
329  $this->current_record = new ilAdvancedMDRecord(0);
330  return true;
331 
332  default:
333  $this->current_record = ilAdvancedMDRecord::_getInstanceByRecordId($this->extractRecordId($a_id));
334  return true;
335  break;
336  }
337  }
338 
346  private function initFieldObject($a_id, $a_type)
347  {
348  switch ($this->getMode()) {
349  case self::MODE_INSERT:
350  case self::MODE_INSERT_VALIDATION:
351  $this->current_field = ilAdvancedMDFieldDefinition::getInstanceByTypeString($a_type);
352  $this->fields[] = $this->current_field;
353  return true;
354 
355  default:
356  // ??? nonsense
357  $this->current_field = ilAdvancedMDRecord::_getInstanceByFieldId($this->extractFieldId($a_id));
358  return true;
359  break;
360  }
361  }
362 
367  {
368  return $this->current_record;
369  }
370 
376  private function getCurrentField()
377  {
378  return $this->current_field;
379  }
380 
388  private function extractRecordId($a_id_string)
389  {
390  // first lookup import id
391  if ($record_id = ilAdvancedMDRecord::_lookupRecordIdByImportId($a_id_string)) {
392  $this->record_exists = true;
393  return $record_id;
394  }
395  return 0;
396  }
397 
398 
399 
407  private function appendErrorMessage($a_msg)
408  {
409  $this->is_error = true;
410  $this->error_msg[] = $a_msg;
411  }
412 
420  private function storeRecords()
421  {
422  switch ($this->getMode()) {
423  case self::MODE_INSERT_VALIDATION:
424  case self::MODE_UPDATE_VALIDATION:
425  return true;
426 
427  case self::MODE_INSERT:
428  // set local context
429  if (is_array($this->context)) {
430  $this->getCurrentRecord()->setParentObject($this->context["obj_id"]);
431  $this->getCurrentRecord()->setAssignedObjectTypes(array(
432  array(
433  "obj_type" => $this->context["obj_type"],
434  "sub_type" => $this->context["sub_type"],
435  "optional" => false
436  )));
437  }
438 
439  $this->getCurrentRecord()->save();
440  break;
441  }
442  foreach ($this->fields as $field) {
443  $field->setRecordId($this->getCurrentRecord()->getRecordId());
444  switch ($this->getMode()) {
445  case self::MODE_INSERT:
446  $field->save();
447  foreach ($this->field_translations as $field_id => $field_info) {
448  if (strcmp($field_id, $field->getImportId()) !== 0) {
449  continue;
450  }
451  foreach ((array) $field_info as $language => $field_translation) {
452  $translation = new ilAdvancedMDFieldTranslation(
453  (int) $field->getFieldId(),
454  (string) $field_translation['title'],
455  (string) $field_translation['description'],
456  (string) $language
457  );
458  $translation->insert();
459  }
460  }
461 
462  // see getRecordMap()
463  $this->log->debug("add to record map, rec id: " . $this->getCurrentRecord()->getRecordId() .
464  ", import id: " . $field->getImportId() . ", field id:" . $field->getFieldId());
465  $this->rec_map[$this->getCurrentRecord()->getRecordId()][$field->getImportId()] = $field->getFieldId();
466  break;
467  }
468  }
470  $translations->addTranslationEntry($this->getCurrentRecord()->getDefaultLanguage(), true);
471  $translations->updateTranslations(
472  $this->getCurrentRecord()->getDefaultLanguage(),
473  (string) $this->getCurrentRecord()->getTitle(),
474  (string) $this->getCurrentRecord()->getDescription()
475  );
476 
477  foreach ($this->translations as $lang_key => $translation_info) {
478  ilLoggerFactory::getLogger('root')->dump($translation_info, ilLogLevel::ERROR);
479  if (!$translations->isConfigured($lang_key)) {
480  $translations->addTranslationEntry($lang_key);
481  }
482  $translations->updateTranslations(
483  $lang_key,
484  (string) $translation_info['title'],
485  (string) $translation_info['description']
486  );
487  }
488 
489  }
490 
491  public function setContext($a_obj_id, $a_obj_type, $a_sub_type = null)
492  {
493  if (!$a_sub_type) {
494  $a_sub_type = "-";
495  }
496 
497  $this->context = array(
498  "obj_id" => $a_obj_id,
499  "obj_type" => $a_obj_type,
500  "sub_type" => $a_sub_type
501  );
502  }
503 
504  public function getRecordMap()
505  {
506  return $this->rec_map;
507  }
508 }
Scope restrictions for advanced md records.
setHandlers($a_xml_parser)
set event handlers
const IL_INST_ID
Definition: constants.php:38
static _exists($a_id, $a_reference=false, $a_type=null)
checks if an object exists in object_data
initFieldObject($a_id, $a_type)
Init field definition object.
static parseImportId($a_import_id)
Parse an ilias import id Typically of type il_[IL_INST_ID]_[OBJ_TYPE]_[OBJ_ID] returns array( &#39;orig&#39; ...
SaxParserException thrown by ilSaxParser if property throwException is set.
handlerEndTag($a_xml_parser, $a_name)
Handler for end tags.
startParsing()
stores xml data in array
handlerCharacterData($a_xml_parser, $a_data)
handler for character data
Base class for sax-based expat parsing extended classes need to overwrite the method setHandlers and ...
static _getInstanceByRecordId($a_record_id)
Get instance by record id.
handlerBeginTag($a_xml_parser, $a_name, $a_attribs)
Handler for start tags.
extractRecordId($a_id_string)
Extract id.
$errors fields
Definition: imgupload.php:51
initRecordObject($a_id)
Init record object.
setContext($a_obj_id, $a_obj_type, $a_sub_type=null)
getCurrentField()
get current field definition private
__construct(Container $dic, ilPlugin $plugin)
static lookupId($a_lang_key)
Lookup obj_id of language ilDB $ilDB.
static getLogger($a_component_id)
Get component logger.
SAX based XML parser for record import files.
static getInstanceByTypeString($a_type)
Get instance by type string (used by import)
Class ilAdvancedMDFieldTranslation.
static _lookupRecordIdByImportId($a_ilias_id)
Lookup record Id by import id.