ILIAS  release_5-1 Revision 5.0.0-5477-g43f3e3fab5
class.ilObjAICCCourseInterchangeFiles.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 */
28 {
30  var $data;
32  var $requiredFiles=array("crs", "au", "cst", "des");
33  var $optionalFiles=array("cmp", "ort", "pre");
34 
36  $this->errorText=array();
37  $this->coursefiles=array();
38 
39  }
40 
41  //searching for aicc files, beginning in $dir
42  // sometimes they are in the main dir - sometimes not
43  // sometimes uppercase - sometimes not
44  function findFiles($dir) {
45  $suffixes=array_merge($this->requiredFiles,$this->optionalFiles);
46  $files=$this->getAllFiles($dir);
47  foreach ($files as $file) {
48  foreach($suffixes as $suffix) {
49  if (strcasecmp(substr($file, -(strlen($suffix)+1)), ".".$suffix)==0)
50  $this->coursefiles[$suffix] = $file;
51  }
52  }
53 
54  //check for required files
55  $missingFiles = array_diff ($this->requiredFiles, array_keys($this->coursefiles));
56  if (count($missingFiles)==4)
57  $this->errorText[]="Missing all required files.<br>You want to check if your learning module is of a different type.";
58  else if (count($missingFiles)>0)
59  $this->errorText[]="Missing required file(s): ".implode("<bR>", $missingFiles);
60  }
61 
62  function readFiles() {
63  $this->data=array();
64 
65  foreach ($this->coursefiles as $suffix=>$filename) {
66  if ($suffix=="crs")
67  $this->data[$suffix]=$this->readCRS($filename);
68  else
69  $this->data[$suffix]=$this->readCSVFile($filename);
70  }
71 
72  //Prepare Data-Array: all keys to lower
73  $this->data=$this->arraykeys_tolower($this->data);
74  }
75 
76  function getDescriptor($system_id) {
77  foreach ($this->data["des"] as $row) {
78  if (strcasecmp ($row["system_id"],$system_id)==0)
79  return $row;
80  }
81  }
82 
83  function validate() {
84  $this->checkRequiredKeys();
85  $this->checkStructure();
86  }
87 
88  function checkRequiredKeys() {
89  //AU
90  $requiredKeys=array("system_id", "type", "command_line", "file_name",
91  "max_score", "mastery_score", "max_time_allowed",
92  "time_limit_action", "system_vendor", "core_vendor",
93  "web_launch", "au_password");
94  $this->checkCourseFile("au", $this->data["au"], $requiredKeys);
95  $this->checkColumnCount("au", $this->data["au"]);
96 
97  //DES
98  $requiredKeys=array("system_id", "title", "description", "developer_id");
99  $this->checkCourseFile("des", $this->data["des"], $requiredKeys);
100  $this->checkColumnCount("des", $this->data["des"]);
101 
102  //CRS
103  $requiredKeys=array("course_creator", "course_id", "course_system", "course_title",
104  "level", "max_fields_cst", "total_aus", "total_blocks", "version");
105  $this->checkCourseFile("crs", $this->data["crs"], $requiredKeys, "course");
106  $requiredKeys=array("max_normal");
107  $this->checkCourseFile("crs", $this->data["crs"], $requiredKeys, "course_behavior");
108 
109  //CST
110  $requiredKeys=array("block", "member");
111  $this->checkCourseFile("cst", $this->data["cst"], $requiredKeys,0);
112  $this->checkColumnCount("cst", $this->data["cst"]);
113 
114  return $errorText;
115  }
116 
117  function checkCourseFile($fileSuffix, $data, $requiredKeys, $group=0) {
118 
119  if (count($data)>0 && is_array($data[$group])) {
120 
121  $keys=array_keys($data[$group]);
122 
123  $missingKeys = array_diff ($requiredKeys, $keys);
124  $optionalKeys = array_diff ($keys, $requiredKeys);
125 
126  if (count($missingKeys)>0)
127  $this->errorText[]="missing keys in ".strtoupper($fileSuffix)."-File: ".implode(",", $missingKeys);
128 
129  } else if (count($data)>0 && !is_array($data[$group])) {
130  $this->errorText[]="missing Group in ".strtoupper($fileSuffix)."-File: $group";
131  } else {
132  $this->errorText[]="empty ".strtoupper($fileSuffix)."-File";
133  }
134 
135  }
136 
137  function checkColumnCount($fileSuffix, $data) {
138  if (count($data)>0) {
139  $colcount=-1;
140  for ($colnr=0;$colnr<count($data);$colnr++) {
141  if ($colcount==-1)
142  $colcount=count($data[$colnr]);
143  else if ($colcount!=count($data[$colnr]))
144  $this->errorText[]=strtoupper($fileSuffix)."-File: unexpected number of columns in line ".($colnr+2);
145  }
146  }
147  }
148 
149  function checkStructure() {
150 
151  //max member fields in cst-file
152  $max=$this->data[crs][course][max_fields_cst];
153  for ($row=0;$row<count($this->data[cst]);$row++) {
154  $value=$this->data[cst][$row][member];
155  if ((is_array($value) && count($value)>$max) || (!is_array($value) && $max==1)) {
156  $this->errorText[]="CRS-File: max_fields_cst does not match number of fields in the CST-File";
157  return;
158  }
159  }
160 
161  //additional validation statements
162  //
163  //
164 
165  }
166 
167 
168  function readCRS($filename) {
169  $data=@parse_ini_file($filename, TRUE);
170 
171  //crs-file is not a valid iniFile
172  //thats why reading the file again to get course_description
173  $lines=file($filename);
174  for($i=0;$i<count($lines);$i++) {
175  if (trim($lines[$i])=="[Course_Description]") {
176  for ($i++;$i<count($lines);$i++) {
177  if (strlen(trim($lines[$i]))>0) {
178  $data["Course_Description"][description]=$lines[$i];
179  break;
180  }
181  }
182  }
183  }
184 
185  return $data;
186  }
187 
188  function readCSVFile($filename) {
189  $row=1;
190  $handle = fopen($filename, "r");
191  while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
192  if ($row++==1) {
193  $header=$data;
194  } else if (count($data)>1) {
195  $data2=array();
196  for ($col=0; $col<count($data); $col++) {
197  if (array_key_exists($header[$col], $data2)) {
198  $value=$data2[$header[$col]];
199  if (!is_array($value))
200  $data2[$header[$col]]=array($value, utf8_encode($data[$col]));
201  else
202  $data2[$header[$col]][]=utf8_encode($data[$col]);
203  } else
204  $data2[$header[$col]]=utf8_encode($data[$col]);
205  }
206  $rows[]=$data2;
207  }
208  }
209  fclose($handle);
210  return $rows;
211  }
212 
213  function getAllFiles($dir, $arr=array()) {
214  if (substr($dir, -1)!="/")
215  $dir.="/";
216 
217  $handle=opendir($dir);
218  while ($file = readdir ($handle)) {
219  if ($file != "." && $file != "..") {
220  if (is_dir($dir.$file))
221  $arr=$this->getAllFiles($dir.$file, $arr);
222  else
223  $arr[]=$dir.$file;
224  }
225  }
226  closedir($handle);
227  return $arr;
228  }
229 
230  function arraykeys_tolower($arr) {
231  $arr=array_change_key_case($arr, CASE_LOWER);
232  foreach ($arr as $k=>$v) {
233  if (is_array($v))
234  $arr[$k]=$this->arraykeys_tolower($v);
235  }
236  return $arr;
237  }
238 
239  function writeToDatabase($alm_id) {
240  include_once("./Modules/ScormAicc/classes/AICC/class.ilAICCTree.php");
241  include_once("./Modules/ScormAicc/classes/AICC/class.ilAICCCourse.php");
242  include_once("./Modules/ScormAicc/classes/AICC/class.ilAICCUnit.php");
243  include_once("./Modules/ScormAicc/classes/AICC/class.ilAICCBlock.php");
244 
245  //write course to database
246  $course=new ilAICCCourse();
247  $course->setALMId($alm_id);
248  $course->setSystemId("root");
249  $course->setTitle($this->data["crs"]["course"]["course_title"]);
250  $course->setDescription($this->data["crs"]["course_description"]["description"]);
251 
252  $course->setCourseCreator($this->data["crs"]["course"]["course_creator"]);
253  $course->setCourseId($this->data["crs"]["course"]["course_id"]);
254  $course->setCourseSystem($this->data["crs"]["course"]["course_system"]);
255  $course->setCourseTitle($this->data["crs"]["course"]["course_title"]);
256  $course->setLevel($this->data["crs"]["course"]["level"]);
257  $course->setMaxFieldsCst($this->data["crs"]["course"]["max_fields_cst"]);
258  $course->setMaxFieldsOrt($this->data["crs"]["course"]["max_fields_ort"]);
259  $course->setTotalAUs($this->data["crs"]["course"]["total_aus"]);
260  $course->setTotalBlocks($this->data["crs"]["course"]["total_blocks"]);
261  $course->setTotalComplexObj($this->data["crs"]["course"]["total_complex_obj"]);
262  $course->setTotalObjectives($this->data["crs"]["course"]["total_objectives"]);
263  $course->setVersion($this->data["crs"]["course"]["version"]);
264  $course->setMaxNormal($this->data["crs"]["course_behavior"]["max_normal"]);
265  $course->setDescription($this->data["crs"]["course_description"]["description"]);
266  $course->create();
267  $identifier["root"]=$course->getId();
268 
269  //all blocks
270  foreach ($this->data["cst"] as $row) {
271  $system_id=strtolower($row["block"]);
272  if ($system_id!="root") {
273  $unit=new ilAICCBlock();
274  $description=$this->getDescriptor($system_id);
275  $unit->setALMId($alm_id);
276  $unit->setType("sbl");
277  $unit->setTitle($description["title"]);
278  $unit->setDescription($description["description"]);
279  $unit->setDeveloperId($description["developer_id"]);
280  $unit->setSystemId($description["system_id"]);
281  $unit->create();
282  $identifier[$system_id]=$unit->getId();
283  }
284  }
285 
286  //write assignable units to database
287  foreach ($this->data["au"] as $row) {
288  $sysid=strtolower($row["system_id"]);
289  $unit=new ilAICCUnit();
290 
291  $unit->setAUType($row["c_type"]);
292  $unit->setCommand_line($row["command_line"]);
293  $unit->setMaxTimeAllowed($row["max_time_allowed"]);
294  $unit->setTimeLimitAction($row["time_limit_action"]);
295  $unit->setMaxScore($row["max_score"]);
296  $unit->setCoreVendor($row["core_vendor"]);
297  $unit->setSystemVendor($row["system_vendor"]);
298  $unit->setFilename($row["file_name"]);
299  $unit->setMasteryScore($row["mastery_score"]);
300  $unit->setWebLaunch($row["web_launch"]);
301  $unit->setAUPassword($row["au_password"]);
302 
303  $description=$this->getDescriptor($sysid);
304  $unit->setALMId($alm_id);
305  $unit->setType("sau");
306  $unit->setTitle($description["title"]);
307  $unit->setDescription($description["description"]);
308  $unit->setDeveloperId($description["developer_id"]);
309  $unit->setSystemId($description["system_id"]);
310  $unit->create();
311  $identifier[$sysid]=$unit->getId();
312  }
313 
314  //write tree
315  $tree =& new ilAICCTree($alm_id);
316  $tree->addTree($alm_id, $identifier["root"]);
317 
318  //writing members
319  foreach ($this->data["cst"] as $row) {
320  $members=$row["member"];
321  if (!is_array($members))
322  $members=array($members);
323  $parentid=$identifier[strtolower($row["block"])];
324 
325  foreach($members as $member) {
326  $memberid=$identifier[strtolower($member)];
327  $tree->insertNode($memberid, $parentid);
328  }
329  }
330  }
331 
332 }
333 
334 ?>
print $file
AICC Block.
$header
checkCourseFile($fileSuffix, $data, $requiredKeys, $group=0)
AICC Object Tree.
$filename
Definition: buildRTE.php:89