ILIAS  Release_5_0_x_branch Revision 61816
 All Data Structures Namespaces Files Functions Variables Groups Pages
class.ilAdvancedMDFieldDefinition.php
Go to the documentation of this file.
1 <?php
2 /* Copyright (c) 1998-2013 ILIAS open source, Extended GPL, see docs/LICENSE */
3 
4 require_once "Services/ADT/classes/class.ilADTFactory.php";
5 
15 {
16  protected $field_id; // [int]
17  protected $record_id; // [int]
18  protected $import_id; // [string]
19  protected $position; // [int]
20  protected $title; // [string]
21  protected $description; // [string]
22  protected $searchable; // [bool]
23  protected $required; // [bool]
24  protected $adt_def; // [ilADTDefinition]
25  protected $adt; // [ilADT]
26 
27  const TYPE_SELECT = 1;
28  const TYPE_TEXT = 2;
29  const TYPE_DATE = 3;
30  const TYPE_DATETIME = 4;
31  const TYPE_INTEGER = 5;
32  const TYPE_FLOAT = 6;
33  const TYPE_LOCATION = 7;
34  const TYPE_SELECT_MULTI = 8;
35 
42  public function __construct($a_field_id = null)
43  {
44  $this->init();
45  $this->read($a_field_id);
46  }
47 
55  public static function getInstance($a_field_id, $a_type = null)
56  {
57  global $ilDB;
58 
59  if(!$a_type)
60  {
61  $set = $ilDB->query("SELECT field_type".
62  " FROM adv_mdf_definition".
63  " WHERE field_id = ".$ilDB->quote($a_field_id, "integer"));
64  $a_type = $ilDB->fetchAssoc($set);
65  $a_type = $a_type["field_type"];
66  }
67 
68  if(self::isValidType($a_type))
69  {
70  $class = "ilAdvancedMDFieldDefinition".self::getTypeString($a_type);
71  require_once "Services/AdvancedMetaData/classes/Types/class.".$class.".php";
72  return new $class($a_field_id);
73  }
74 
75  throw new ilException("unknown type ".$a_type);
76  }
77 
84  public static function getInstanceByTypeString($a_type)
85  {
86  // see self::getTypeString()
87  $map = array(
88  self::TYPE_TEXT => "Text",
89  self::TYPE_SELECT => "Select",
90  self::TYPE_DATE => "Date",
91  self::TYPE_DATETIME => "DateTime",
92  self::TYPE_FLOAT => "Float",
93  self::TYPE_LOCATION => "Location",
94  self::TYPE_INTEGER => "Integer",
95  self::TYPE_SELECT_MULTI => "SelectMulti"
96  );
97  $map = array_flip($map);
98  if(array_key_exists($a_type, $map))
99  {
100  return self::getInstance(null, $map[$a_type]);
101  }
102  }
103 
111  public static function getInstancesByRecordId($a_record_id, $a_only_searchable = false)
112  {
113  global $ilDB;
114 
115  $defs = array();
116 
117  $query = "SELECT * FROM adv_mdf_definition".
118  " WHERE record_id = ".$ilDB->quote($a_record_id, "integer");
119  if($a_only_searchable)
120  {
121  $query .= " AND searchable = ".$ilDB->quote(1, "integer");
122  }
123  $query .= " ORDER BY position";
124  $set = $ilDB->query($query);
125  while($row = $ilDB->fetchAssoc($set))
126  {
127  $field = self::getInstance(null, $row["field_type"]);
128  $field->import($row);
129  $defs[$row["field_id"]] = $field;
130  }
131 
132  return $defs;
133  }
134 
135  public static function getInstancesByObjType($a_obj_type, $a_active_only = true)
136  {
137  global $ilDB;
138 
139  $defs = array();
140 
141  $query = "SELECT amf.* FROM adv_md_record_objs aro".
142  " JOIN adv_md_record amr ON aro.record_id = amr.record_id".
143  " JOIN adv_mdf_definition amf ON aro.record_id = amf.record_id".
144  " WHERE obj_type = ".$ilDB->quote($a_obj_type,'text');
145  if((bool)$a_active_only)
146  {
147  $query .= " AND active = ".$ilDB->quote(1, "integer");
148  }
149  $query .= " ORDER BY aro.record_id,position";
150  $res = $ilDB->query($query);
151  while($row = $ilDB->fetchAssoc($res))
152  {
153  $field = self::getInstance(null, $row["field_type"]);
154  $field->import($row);
155  $defs[$row["field_id"]] = $field;
156  }
157  return $defs;
158  }
159 
166  public static function getInstanceByImportId($a_import_id)
167  {
168  global $ilDB;
169 
170  $query = "SELECT field_id, field_type FROM adv_mdf_definition".
171  " WHERE import_id = ".$ilDB->quote($a_import_id,'text');
172  $set = $ilDB->query($query);
173  if($ilDB->numRows($set))
174  {
175  $row = $ilDB->fetchAssoc($set);
176  return self::getInstance($row["field_id"], $row["field_type"]);
177  }
178  }
179 
185  public static function getSearchableDefinitionIds()
186  {
187  global $ilDB;
188 
189  $field_ids = array();
190 
191  $query = "SELECT field_id FROM adv_md_record amr".
192  " JOIN adv_mdf_definition amfd ON (amr.record_id = amfd.record_id)".
193  " WHERE active = ".$ilDB->quote(1, "integer").
194  " AND searchable = ".$ilDB->quote(1, "integer");
195  $set = $ilDB->query($query);
196  while($row = $ilDB->fetchAssoc($set))
197  {
198  $field_ids[] = $row["field_id"];
199  }
200  return $field_id;
201  }
202 
209  public static function getADTGroupForDefinitions(array $a_defs)
210  {
211  $factory = ilADTFactory::getInstance();
212  $group_def = $factory->getDefinitionInstanceByType("Group");
213  foreach($a_defs as $def)
214  {
215  $group_def->addElement($def->getFieldId(), $def->getADTDefinition());
216  }
217  $group = $factory->getInstanceByDefinition($group_def);
218 
219  // bind adt instances to definition
220  foreach($group->getElements() as $element_id => $element)
221  {
222  $a_defs[$element_id]->setADT($element);
223  }
224 
225  return $group;
226  }
227 
231  protected function init()
232  {
233  $this->setRequired(false);
234  $this->setSearchable(false);
235  }
236 
237 
238  //
239  // generic types
240  //
241 
247  public static function getValidTypes()
248  {
249  return array(self::TYPE_TEXT, self::TYPE_DATE, self::TYPE_DATETIME,
250  self::TYPE_SELECT, self::TYPE_INTEGER, self::TYPE_FLOAT,
251  self::TYPE_LOCATION, self::TYPE_SELECT_MULTI);
252  }
253 
260  public static function isValidType($a_type)
261  {
262  return in_array((int)$a_type, self::getValidTypes());
263  }
264 
270  abstract public function getType();
271 
278  protected static function getTypeString($a_type)
279  {
280  if(self::isValidType($a_type))
281  {
282  $map = array(
283  self::TYPE_TEXT => "Text",
284  self::TYPE_SELECT => "Select",
285  self::TYPE_DATE => "Date",
286  self::TYPE_DATETIME => "DateTime",
287  self::TYPE_FLOAT => "Float",
288  self::TYPE_LOCATION => "Location",
289  self::TYPE_INTEGER => "Integer",
290  self::TYPE_SELECT_MULTI => "SelectMulti"
291  );
292  return $map[$a_type];
293  }
294  }
295 
301  public function getTypeTitle()
302  {
303  // :TODO: reuse udf stuff here ?!
304  return "udf_type_".strtolower(self::getTypeString($this->getType()));
305  }
306 
307 
308 
309  //
310  // ADT
311  //
312 
318  abstract protected function initADTDefinition();
319 
325  public function getADTDefinition()
326  {
327  if(!$this->adt_def instanceof ilADTDefinition)
328  {
329  $this->adt_def = $this->initADTDefinition();
330  }
331  return $this->adt_def;
332  }
333 
339  public function getADT()
340  {
341  if(!$this->adt instanceof ilADT)
342  {
343  $this->adt = ilADTFactory::getInstance()->getInstanceByDefinition($this->getADTDefinition());
344  }
345  return $this->adt;
346  }
347 
354  protected function setADT(ilADT $a_adt)
355  {
356  if(!$this->adt instanceof ilADT)
357  {
358  $this->adt = $a_adt;
359  }
360  }
361 
362  //
363  // properties
364  //
365 
371  protected function setFieldId($a_id)
372  {
373  $this->field_id = (int)$a_id;
374  }
375 
381  public function getFieldId()
382  {
383  return $this->field_id;
384  }
385 
391  public function setRecordId($a_id)
392  {
393  $this->record_id = (int)$a_id;
394  }
395 
401  public function getRecordId()
402  {
403  return $this->record_id;
404  }
405 
411  public function setImportId($a_id_string)
412  {
413  if($a_id_string !== null)
414  {
415  $a_id_string = trim($a_id_string);
416  }
417  $this->import_id = $a_id_string;
418  }
419 
425  public function getImportId()
426  {
427  return $this->import_id;
428  }
429 
435  public function setPosition($a_pos)
436  {
437  $this->position = (int)$a_pos;
438  }
439 
445  public function getPosition()
446  {
447  return $this->position;
448  }
449 
455  public function setTitle($a_title)
456  {
457  if($a_title !== null)
458  {
459  $a_title = trim($a_title);
460  }
461  $this->title = $a_title;
462  }
463 
469  public function getTitle()
470  {
471  return $this->title;
472  }
473 
479  public function setDescription($a_desc)
480  {
481  if($a_desc !== null)
482  {
483  $a_desc = trim($a_desc);
484  }
485  $this->description = $a_desc;
486  }
487 
493  public function getDescription()
494  {
495  return $this->description;
496  }
497 
503  public function setSearchable($a_status)
504  {
505  $this->searchable = (bool)$a_status;
506  }
507 
513  public function isSearchable()
514  {
515  return $this->searchable;
516  }
517 
523  public function setRequired($a_status)
524  {
525  $this->required = (bool)$a_status;
526  }
527 
533  public function isRequired()
534  {
535  return $this->required;
536  }
537 
538 
539  //
540  // definition (NOT ADT-based)
541  //
542 
548  protected function importFieldDefinition(array $a_def)
549  {
550 
551  }
552 
558  protected function getFieldDefinition()
559  {
560  // type-specific properties
561  }
562 
569  {
570  // type-specific properties
571  }
572 
579  protected function addCustomFieldToDefinitionForm(ilPropertyFormGUI $a_form, $a_disabled = false)
580  {
581  // type-specific
582  }
583 
591  {
592  global $lng;
593 
594  $perm = $a_permissions->hasPermissions(
596  $this->getFieldId(),
597  array(
606  ));
607 
608  // title
609  $title = new ilTextInputGUI($lng->txt('title'), 'title');
610  $title->setValue($this->getTitle());
611  $title->setSize(20);
612  $title->setMaxLength(70);
613  $title->setRequired(true);
614  $a_form->addItem($title);
615 
617  {
618  $title->setDisabled(true);
619  }
620 
621  // desc
622  $desc = new ilTextAreaInputGUI($lng->txt('description'), 'description');
623  $desc->setValue($this->getDescription());
624  $desc->setRows(3);
625  $desc->setCols(50);
626  $a_form->addItem($desc);
627 
629  {
630  $desc->setDisabled(true);
631  }
632 
633  // searchable
634  $check = new ilCheckboxInputGUI($lng->txt('md_adv_searchable'), 'searchable');
635  $check->setChecked($this->isSearchable());
636  $check->setValue(1);
637  $a_form->addItem($check);
638 
640  {
641  $check->setDisabled(true);
642  }
643 
644  /* required
645  $check = new ilCheckboxInputGUI($lng->txt('md_adv_required'), 'required');
646  $check->setChecked($this->isRequired());
647  $check->setValue(1);
648  $a_form->addItem($check);
649  */
650 
651  $this->addCustomFieldToDefinitionForm($a_form,
653  }
654 
661  {
662  // type-specific
663  }
664 
672  {
673  if(!$a_form->getItemByPostVar("title")->getDisabled())
674  {
675  $this->setTitle($a_form->getInput("title"));
676  }
677  if(!$a_form->getItemByPostVar("description")->getDisabled())
678  {
679  $this->setDescription($a_form->getInput("description"));
680  }
681  if(!$a_form->getItemByPostVar("searchable")->getDisabled())
682  {
683  $this->setSearchable($a_form->getInput("searchable"));
684  }
685 
686  if($a_permissions->hasPermission(
688  $this->getFieldId(),
691  {
692  $this->importCustomDefinitionFormPostValues($a_form);
693  }
694  }
695 
697  {
698  return false;
699  }
700 
702  {
703  // type-specific
704  }
705 
707  {
708  $a_form->getItemByPostVar("title")->setDisabled(true);
709  $a_form->getItemByPostVar("description")->setDisabled(true);
710  $a_form->getItemByPostVar("searchable")->setDisabled(true);
711 
712  // checkboxes have no hidden on disabled
713  if($a_form->getInput("searchable"))
714  {
715  $hidden = new ilHiddenInputGUI("searchable");
716  $hidden->setValue(1);
717  $a_form->addItem($hidden);
718  }
719 
721  }
722 
723 
724  //
725  // definition CRUD
726  //
727 
733  protected function getLastPosition()
734  {
735  global $ilDB;
736 
737  $sql = "SELECT max(position) pos".
738  " FROM adv_mdf_definition".
739  " WHERE record_id = ".$ilDB->quote($this->getRecordId(), "integer");
740  $set = $ilDB->query($sql);
741  if($ilDB->numRows($set))
742  {
743  $pos = $ilDB->fetchAssoc($set);
744  return (int)$pos["pos"];
745  }
746 
747  return 0;
748  }
749 
756  protected function generateImportId($a_field_id)
757  {
758  return 'il_'.IL_INST_ID.'_adv_md_field_'.$a_field_id;
759  }
760 
766  protected function getDBProperties()
767  {
768  $fields = array(
769  "field_type" => array("integer", $this->getType()),
770  "record_id" => array("integer", $this->getRecordId()),
771  "import_id" => array("text", $this->getImportId()),
772  "title" => array("text", $this->getTitle()),
773  "description" => array("text", $this->getDescription()),
774  "position" => array("integer", $this->getPosition()),
775  "searchable" => array("integer", $this->isSearchable()),
776  "required" => array("integer", $this->isRequired())
777  );
778 
779  $def = $this->getFieldDefinition();
780  if(is_array($def))
781  {
782  $fields["field_values"] = array("text", serialize($def));
783  }
784 
785  return $fields;
786  }
787 
793  protected function import(array $a_data)
794  {
795  $this->setFieldId($a_data["field_id"]);
796 
797  $this->setRecordId($a_data["record_id"]);
798  $this->setImportId($a_data["import_id"]);
799  $this->setTitle($a_data["title"]);
800  $this->setDescription($a_data["description"]);
801  $this->setPosition($a_data["position"]);
802  $this->setSearchable($a_data["searchable"]);
803  $this->setRequired($a_data["required"]);
804 
805  if($a_data["field_values"])
806  {
807  $this->importFieldDefinition(unserialize($a_data["field_values"]));
808  }
809  }
810 
814  protected function read($a_field_id)
815  {
816  global $ilDB;
817 
818  if(!(int)$a_field_id)
819  {
820  return;
821  }
822 
823  $sql = "SELECT * FROM adv_mdf_definition".
824  " WHERE field_id = ".$ilDB->quote($a_field_id, "integer");
825  $set = $ilDB->query($sql);
826  if($ilDB->numRows($set))
827  {
828  $row = $ilDB->fetchAssoc($set);
829  $this->import($row);
830  }
831  }
832 
836  public function save()
837  {
838  global $ilDB;
839 
840  if($this->getFieldId())
841  {
842  return $this->update();
843  }
844 
845  $next_id = $ilDB->nextId("adv_mdf_definition");
846 
847  // append
848  $this->setPosition($this->getLastPosition()+1);
849 
850  // needs unique import id
851  if(!$this->getImportId())
852  {
853  $this->setImportId($this->generateImportId($next_id));
854  }
855 
856  $fields = $this->getDBProperties();
857  $fields["field_id"] = array("integer", $next_id);
858 
859  $ilDB->insert("adv_mdf_definition", $fields);
860  }
861 
865  public function update()
866  {
867  global $ilDB;
868 
869  if(!$this->getFieldId())
870  {
871  return $this->save();
872  }
873 
874  $ilDB->update("adv_mdf_definition",
875  $this->getDBProperties(),
876  array("field_id"=>array("integer", $this->getFieldId())));
877  }
878 
882  public function delete()
883  {
884  global $ilDB;
885 
886  if(!$this->getFieldId())
887  {
888  return;
889  }
890 
891  // delete all values
892  include_once("Services/AdvancedMetaData/classes/class.ilAdvancedMDValues.php");
894 
895  $query = "DELETE FROM adv_mdf_definition".
896  " WHERE field_id = ".$ilDB->quote($this->getFieldId(), "integer");
897  $ilDB->manipulate($query);
898  }
899 
900 
901  //
902  // export/import
903  //
904 
912  public function toXML(ilXmlWriter $a_writer)
913  {
914  $a_writer->xmlStartTag('Field',array(
915  'id' => $this->generateImportId($this->getFieldId()),
916  'searchable' => ($this->isSearchable() ? 'Yes' : 'No'),
917  'fieldType' => self::getTypeString($this->getType())));
918 
919  $a_writer->xmlElement('FieldTitle',null,$this->getTitle());
920  $a_writer->xmlElement('FieldDescription',null,$this->getDescription());
921  $a_writer->xmlElement('FieldPosition',null,$this->getPosition());
922 
923  $this->addPropertiesToXML($a_writer);
924 
925  $a_writer->xmlEndTag('Field');
926  }
927 
933  protected function addPropertiesToXML(ilXmlWriter $a_writer)
934  {
935  // type-specific properties
936  }
937 
944  public function importXMLProperty($a_key, $a_value)
945  {
946 
947  }
948 
955  abstract public function getValueForXML(ilADT $element);
956 
962  abstract public function importValueFromXML($a_cdata);
963 
972  public function importFromECS($a_ecs_type, $a_value, $a_sub_id)
973  {
974  return false;
975  }
976 
977 
978  //
979  // presentation
980  //
981 
987  public function prepareElementForEditor(ilADTFormBridge $a_bridge)
988  {
989  // type-specific
990  }
991 
992 
993  //
994  // search
995  //
996 
1003  public function getSearchQueryParserValue(ilADTSearchBridge $a_adt_search)
1004  {
1005  return '';
1006  }
1007 
1014  public function getSearchValueSerialized(ilADTSearchBridge $a_adt_search)
1015  {
1016  return $a_adt_search->getSerializedValue();
1017  }
1018 
1025  public function setSearchValueSerialized(ilADTSearchBridge $a_adt_search, $a_value)
1026  {
1027  return $a_adt_search->setSerializedValue($a_value);
1028  }
1029 
1037  protected function parseSearchObjects(array $a_records, array $a_object_types)
1038  {
1039  global $ilDB;
1040 
1041  $res = array();
1042 
1043  $obj_ids = array();
1044  foreach($a_records as $record)
1045  {
1046  if($record["sub_type"] == "-")
1047  {
1048  $obj_ids[] = $record["obj_id"];
1049  }
1050  }
1051 
1052  $sql = "SELECT obj_id,type".
1053  " FROM object_data".
1054  " WHERE ".$ilDB->in("obj_id", $obj_ids, "", "integer").
1055  " AND ".$ilDB->in("type", $a_object_types, "", "text");
1056  $set = $ilDB->query($sql);
1057  while($row = $ilDB->fetchAssoc($set))
1058  {
1059  $res[] = $row;
1060  }
1061 
1062  return $res;
1063  }
1064 
1065  public function searchSubObjects(ilADTSearchBridge $a_adt_search, $a_obj_id, $sub_obj_type)
1066  {
1067  include_once('Services/ADT/classes/ActiveRecord/class.ilADTActiveRecordByType.php');
1069 
1070  // :TODO:
1071  if($a_adt_search instanceof ilADTLocationSearchBridgeSingle)
1072  {
1073  $element_id = "loc";
1074  }
1075 
1076  $condition = $a_adt_search->getSQLCondition($element_id);
1077  if($condition)
1078  {
1079  $objects = ilADTActiveRecordByType::find("adv_md_values", $this->getADT()->getType(), $this->getFieldId(), $condition);
1080  if(sizeof($objects))
1081  {
1082  $res = array();
1083  foreach($objects as $item)
1084  {
1085  if($item["obj_id"] == $a_obj_id &&
1086  $item["sub_type"] == $sub_obj_type)
1087  {
1088  $res[] = $item["sub_id"];
1089  }
1090  }
1091  return $res;
1092  }
1093  }
1094 
1095  return array();
1096  }
1097 
1108  public function searchObjects(ilADTSearchBridge $a_adt_search, ilQueryParser $a_parser, array $a_object_types, $a_locate, $a_search_type)
1109  {
1110  // search type only supported/needed for text
1111 
1112  include_once('Services/ADT/classes/ActiveRecord/class.ilADTActiveRecordByType.php');
1113  $condition = $a_adt_search->getSQLCondition(ilADTActiveRecordByType::SINGLE_COLUMN_NAME);
1114  if($condition)
1115  {
1116  $objects = ilADTActiveRecordByType::find("adv_md_values", $this->getADT()->getType(), $this->getFieldId(), $condition, $a_locate);
1117  if(sizeof($objects))
1118  {
1119  return $this->parseSearchObjects($objects, $a_object_types);
1120  }
1121  return array();
1122  }
1123  }
1124 
1131  public function getLuceneSearchString($a_value)
1132  {
1133  return $a_value;
1134  }
1135 
1141  public function prepareElementForSearch(ilADTSearchBridge $a_bridge)
1142  {
1143  // type-specific
1144  }
1145 }
1146 
1147 ?>