Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
hipo_job_export_online_quiz_to_xml.inc
1 <?php
17 require_once SQ_SYSTEM_ROOT.'/core/hipo/hipo_job.inc';
18 require_once SQ_FUDGE_PATH.'/general/file_system.inc';
19 
20 
40 {
41 
42 
48  function HIPO_Job_Export_Online_Quiz_To_XML($code_name='')
49  {
50  $this->uses_trans = FALSE;
51  $this->HIPO_Job($code_name);
52 
53  }//end constructor
54 
55 
62  function getCodeName()
63  {
64  return parent::getCodeName().'-'.$this->_running_vars['root_node'];
65 
66  }//end getCodeName()
67 
68 
75  function getHipoName()
76  {
77  return translate('hipo_name_export_online_quiz_to_xml');
78 
79  }//end getHipoName()
80 
81 
89  function getInitialStepData()
90  {
91  return Array(
92  Array(
93  'name' => 'Initialising Export',
94  'function_call' => Array(
95  'process_function' => 'initialiseExport',
96  ),
97  'running_mode' => 'server',
98  'auto_step' => TRUE,
99  'skip_step' => FALSE,
100  'allow_cancel' => TRUE,
101  'percent_done' => 0,
102  'complete' => FALSE,
103  'message' => ''
104  ),
105  Array(
106  'name' => 'Generating XML',
107  'function_call' => Array(
108  'process_function' => 'generateXML',
109  ),
110  'running_mode' => 'server',
111  'auto_step' => TRUE,
112  'skip_step' => FALSE,
113  'allow_cancel' => TRUE,
114  'percent_done' => 0,
115  'complete' => FALSE,
116  'message' => ''
117  ),
118  Array(
119  'name' => 'Finalising Export',
120  'function_call' => Array(
121  'process_function' => 'finaliseExport',
122  ),
123  'running_mode' => 'server',
124  'auto_step' => TRUE,
125  'skip_step' => FALSE,
126  'allow_cancel' => TRUE,
127  'percent_done' => 0,
128  'complete' => FALSE,
129  'message' => ''
130  ),
131  );
132 
133  }//end getInitialStepData()
134 
135 
142  function prepare()
143  {
144  if (empty($this->_running_vars['root_node'])) {
145  trigger_error('There is no root node specified', E_USER_WARNING);
146  return FALSE;
147  }
148 
149  if (empty($this->_running_vars['type_codes'])) {
150  trigger_error ('There is no type codes specified', E_USER_NOTICE);
151  return FALSE;
152  }
153 
154  if (!is_dir($this->_running_vars['export_dir'])) {
155  if (!create_directory($this->_running_vars['export_dir'])) return FALSE;
156  }
157 
158  $this->_running_vars['todo_export_assets'] = Array();
159  $this->_running_vars['done_export_assets'] = Array();
160  //to manage the opening/close of tags
161  $this->_running_vars['opened_tags'] = Array();
162  //these type codes are already packaged inside page_online_quiz
163  $this->_running_vars['skip_type_codes'] = Array('online_quiz_question_multichoice', 'online_quiz_question_group');
164 
165  //Important that we do not filter the asset types, link types or permissions here so the asset map hierarchy can be tracked fully.
166  $children = $GLOBALS['SQ_SYSTEM']->am->getAllChildLinks($this->_running_vars['root_node'], SQ_SC_LINK_SIGNIFICANT);
167  //Add the root node
168  $root_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($this->_running_vars['root_node']);
169  array_unshift($children, Array (
170  "lvl" => "0",
171  "assetid" => $root_asset->id,
172  "type_code" => $root_asset->type(),
173  "link_type" => "1",
174  "is_dependant" => "0",
175  ));
176  $this->_running_vars['todo_export_assets'] = $children;
177 
178  return parent::prepare();
179 
180  }//end prepare()
181 
182 
189  function freestyle()
190  {
191  if (!$this->initialiseExport($this->_steps[0], get_class($this))) {
192  return FALSE;
193  }
194 
195  while (!empty($this->_running_vars['todo_export_assets'])) {
196  if (!$this->generateXML($this->_steps[1], get_class($this))) {
197  return FALSE;
198  }
199  }
200 
201  if (!$this->finaliseExport($this->_steps[2], get_class($this))) {
202  return FALSE;
203  }
204 
205  return TRUE;
206 
207  }//end freestyle()
208 
209 
219  function initialiseExport(&$step_data, $prefix)
220  {
221  ob_start();
222  echo "<?xml version=\"1.0\" encoding=\"".SQ_CONF_DEFAULT_CHARACTER_SET."\"?>\n";
223  echo "<data_export>\n";
224  $output = ob_get_clean();
225  file_put_contents($this->_running_vars['export_dir'].'/export.xml', $output, FILE_APPEND | LOCK_EX);
226 
227  $step_data['percent_done'] = 100;
228  $step_data['complete'] = TRUE;
229 
230  return TRUE;
231 
232  }//end initialiseExport()
233 
234 
244  function generateXML(&$step_data, $prefix)
245  {
246  ob_start();
247 
248  if (!empty($this->_running_vars['todo_export_assets'])) {
249  $todo_asset = array_shift($this->_running_vars['todo_export_assets']);
250 
251  //do we need to close any opened tags in the stack?
252  foreach (array_reverse($this->_running_vars['opened_tags'], TRUE) as $level_no => $tag_name){
253  if ($todo_asset['lvl'] <= $level_no){
254  echo "</".$tag_name.">\n";
255  unset($this->_running_vars['opened_tags'][$level_no]);
256  }
257  }
258 
259  $assetid = $todo_asset['assetid'];
260  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
261  if (!is_null($asset)){
262  //Skip TYPE 3 links, dependant assets and certain type codes. Doubt candidate assets will appear under these.
263  //Note that skipping an asset will cause any candidate children to be exported higher up in the hierarchy.
264  if (!$todo_asset['is_dependant'] && !($todo_asset['link_type'] == SQ_LINK_TYPE_3) && !in_array($todo_asset['type_code'], $this->_running_vars['skip_type_codes'])){
265  $step_data['message'] = "Generating XML for $asset->name (Id: #$asset->id)";
266  echo "<".$asset->type()." assetid=\"".$asset->id."\">\n";
267  $this->_running_vars['opened_tags'][$todo_asset['lvl']] = $asset->type();
268  $method_name = 'generate'.str_replace('_', '', get_class($asset)).'XML';
269  if (in_array($todo_asset['type_code'], $this->_running_vars['type_codes']) && method_exists($this, $method_name) && $asset->readAccess()){
270  $this->$method_name($asset);
271  } else {
272  //just print out the asset name
273  echo "<name><![CDATA[".$asset->name."]]></name>\n";
274  }
275  } else {
276  $step_data['message'] = translate('hipo_skipping_asset', $assetid);
277  }
278  } else {
279  $step_data['message'] = translate('hipo_skipping_asset', $assetid);
280  $this->_addError("Could not load Asset (Id: #$assetid)");
281  }
282  $this->_running_vars['done_export_assets'][] = $assetid;
283  }
284 
285  $output = ob_get_clean();
286  file_put_contents($this->_running_vars['export_dir'].'/export.xml', $output, FILE_APPEND | LOCK_EX);
287 
288  if (empty($this->_running_vars['todo_export_assets'])) {
289  $step_data['percent_done'] = 100;
290  $step_data['complete'] = TRUE;
291  } else {
292  $total = count($this->_running_vars['todo_export_assets']) + count($this->_running_vars['done_export_assets']);
293  $step_data['percent_done'] = (count($this->_running_vars['done_export_assets']) / $total) * 100;
294  $step_data['complete'] = FALSE;
295  }
296 
297  return TRUE;
298 
299  }//end generateXML()
300 
301 
311  function finaliseExport(&$step_data, $prefix)
312  {
313  ob_start();
314 
315  //final closing of tags
316  foreach (array_reverse($this->_running_vars['opened_tags'], TRUE) as $level_no => $tag_name){
317  echo "</".$tag_name.">\n";
318  unset($this->_running_vars['opened_tags'][$level_no]);
319  }
320 
321  echo "</data_export>\n";
322 
323  $output = ob_get_clean();
324  file_put_contents($this->_running_vars['export_dir'].'/export.xml', $output, FILE_APPEND | LOCK_EX);
325 
326  //Translate any left over Matrix URLs
327  $content = file_get_contents($this->_running_vars['export_dir'].'/export.xml');
328  $GLOBALS['SQ_SYSTEM']->_translateMatrixURL($content);
329  file_put_contents($this->_running_vars['export_dir'].'/export.xml', $content, LOCK_EX);
330 
331  //This piece of code just formats the XML nicely with indents.
332  //LIBXML_NOBLANKS & LIBXML_NOEMPTYTAG balance each other out. Some flags had to be set to get the formatting to work.
333  $doc = new DOMDocument();
334  $doc->formatOutput = TRUE;
335  $doc->load($this->_running_vars['export_dir'].'/export.xml', LIBXML_NOBLANKS);
336  $doc->save($this->_running_vars['export_dir'].'/export.xml', LIBXML_NOEMPTYTAG);
337 
338  $step_data['percent_done'] = 100;
339  $step_data['complete'] = TRUE;
340 
341  return TRUE;
342 
343  }//end finaliseExport()
344 
345 
355  {
356  $settings = isset($this->_running_vars['export_settings'][$asset->type()]) ? $this->_running_vars['export_settings'][$asset->type()] : Array();
357 
358  $start_tag = array_get_index($settings, 'start_tag', '');
359  $end_tag = array_get_index($settings, 'end_tag', '');
360  $paint_method = array_get_index($settings, 'paint_method', 'raw');
361 
362  echo "<name><![CDATA[".trim($asset->attr('name'))."]]></name>";
363  echo "<short_name><![CDATA[".trim($asset->attr('short_name'))."]]></short_name>";
364 
365  ob_start();
366  if ($paint_method == 'default_layout'){
367  $layout_id = $GLOBALS['SQ_SYSTEM']->am->getValueFromURL(strip_url($asset->getURL(), TRUE), 'paint_layout::system::frontend');
368  if (!empty($layout_id)){
369  $asset->printBodyWithPaintLayout($layout_id);
370  } else {
371  $asset->printBody();
372  }
373  } else {
374  $asset->printBody();
375  }
376  $contents = ob_get_clean();
377 
378  if (!empty($start_tag) || !empty($end_tag)) {
379  $start_tag = preg_quote($start_tag, '/');
380  $end_tag = preg_quote($end_tag, '/');
381  $pattern = "/$start_tag(.*)$end_tag/s";
382  $matches = Array();
383  $matched = preg_match($pattern, $contents, $matches);
384  if ($matched) $contents = $matches[1];
385 
386  }
387 
388  echo "<contents><![CDATA[".trim($contents)."]]></contents>";
389 
390  }//end generatePageStandardXML()
391 
392 
402  {
403  echo "<name><![CDATA[".trim($asset->attr('name'))."]]></name>\n";
404 
405  $pool_links = $GLOBALS['SQ_SYSTEM']->am->getLinks($asset->id, SQ_LINK_NOTICE, '', FALSE, 'major', 'root');
406 
407  $question_group_ids = Array();
408  foreach ($pool_links as $link){
409  //the pool is a question group itself
410  $pool_asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($link['minorid']);
411  if ($pool_asset && $pool_asset->type() == 'online_quiz_question_group'){
412  $question_group_ids[$link['minorid']][] = $link['minorid'];
413  }
414  //the pool has a parent question group
415  $question_groups = $GLOBALS['SQ_SYSTEM']->am->getParents($link['minorid'], 'online_quiz_question_group', TRUE, NULL, SQ_PERMISSION_READ);
416  foreach (array_keys($question_groups) as $question_group_id) {
417  $question_group_ids[$question_group_id][] = $link['minorid'];
418  }
419  }
420 
421  foreach ($question_group_ids as $question_group_id => $pool_nodes){
422  $question_group = $GLOBALS['SQ_SYSTEM']->am->getAsset($question_group_id);
423  if (is_null($question_group)) continue;
424  //need to do referencing in the XML because coming up with a nested XML structure for this is very messy!
425  echo "<".$question_group->type()." assetid=\"".$question_group->id."\" pool_nodes=\"".implode(',', $pool_nodes)."\">\n";
426  echo "<name><![CDATA[".trim($question_group->attr('name'))."]]></name>\n";
427  $score_categories = $question_group->attr('score_categories');
428  foreach ($score_categories as $category){
429  echo "<score_category>\n";
430  echo "<name><![CDATA[".trim($category['name'])."]]></name>\n";
431  echo "<min_score>".$category['min_score']."</min_score>\n";
432  echo "<max_score>".$category['max_score']."</max_score>\n";
433  echo "<content><![CDATA[".trim($category['content'])."]]></content>\n";
434  echo "</score_category>\n";
435  }
436  echo "</".$question_group->type().">\n";
437  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($question_group);
438  }
439 
440  $order = 1;
441  $question_pool_setup = $asset->attr('question_pool_setup');
442  foreach ($pool_links as $link){
443  echo "<pool_node id=\"".$link['minorid']."\">\n";
444 
445  if ($asset->attr('interactive_mode')){
446  $info = $question_pool_setup[$link['minorid']];
447  echo "<size>".$info['size']."</size>\n";
448  echo "<retries>".$info['retries']."</retries>\n";
449  echo "<order>$order</order>\n";
450  }
451 
452  $questions = $GLOBALS['SQ_SYSTEM']->am->getChildren($link['minorid'], 'online_quiz_question_multichoice', TRUE, NULL, NULL, SQ_PERMISSION_READ);
453  foreach (array_keys($questions) as $question_id){
454  $question = $GLOBALS['SQ_SYSTEM']->am->getAsset($question_id);
455  if (is_null($question)) continue;
456 
457  echo "<".$question->type()." assetid=\"".$question->id."\">\n";
458  echo "<name><![CDATA[".trim($question->attr('name'))."]]></name>\n";
459  echo "<question_text><![CDATA[".trim($question->getQuestionText())."]]></question_text>\n";
460  echo "<question_note><![CDATA[".trim($question->getQuestionNote())."]]></question_note>\n";
461 
462  $options = $question->attr('response_form');
463  foreach ($options as $option_key => $option_info){
464  echo "<option>\n";
465  echo "<text><![CDATA[".trim($option_info['text'])."]]></text>\n";
466  echo "<points>".$option_info['points']."</points>\n";
467  echo "<response_supplement><![CDATA[".trim($option_info['response_supplement'])."]]></response_supplement>\n";
468  echo "</option>\n";
469  }
470  echo "</".$question->type().">\n";
471  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($question);
472  }
473  echo "</pool_node>\n";
474  $order++;
475  }
476 
477  }//end generatePageOnlineQuizXML
478 
479 
480 }//end class
481 ?>