Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
simple_form.inc
1 <?php
18 require_once SQ_INCLUDE_PATH.'/asset.inc';
19 require_once SQ_FUDGE_PATH.'/general/general.inc';
20 require_once SQ_CORE_PACKAGE_PATH.'/interfaces/bridge/bridge.inc';
21 
22 
34 class Simple_Form extends Asset implements Bridge
35 {
36 
37 
44  var $_errors = Array();
45 
46 
53  var $_answers = Array();
54 
55 
64  function Simple_Form($assetid=0)
65  {
66  $this->_ser_attrs = TRUE;
67  $this->Asset($assetid);
68 
69  }//end constructor
70 
71 
72 //-- BRIDGE FUNCTIONS --//
73 
74 
89  function getAsset($assetid, $type_code='', $mute_errors=FALSE)
90  {
91  $asset = NULL;
92  $id_parts = explode(':', $assetid);
93 
94  if (isset($id_parts[1])) {
95  $shadowid = $id_parts[1];
96  } else {
97  return $asset;
98  }
99 
100  // Questions follow the format '<assetid>:q<shadowid>'
101  if ($shadowid{0} == 'q') {
102 
103  // pick up the question in question (!)
104  $questions = $this->attr('questions');
105  $questionid = substr($shadowid, 1, strlen($shadowid));
106  if (empty($questions[$questionid])) return $asset;
107 
108  $q_type_code = $questions[$questionid]['type_code'];
109 
110  // not fussed about type code?
111  if (empty($type_code)) $type_code = $q_type_code;
112 
113  // only give the asset back if of the right type code
114  if (in_array($q_type_code, $GLOBALS['SQ_SYSTEM']->am->getTypeDescendants($type_code, TRUE))) {
115  $questions[$questionid]['questionid'] = $questionid;
116  $GLOBALS['SQ_SYSTEM']->am->includeAsset($q_type_code);
117 
118  // this eval returns the necessary object for the question type
119  $asset = new $q_type_code($this->id, $questions[$questionid]);
120  }
121  }
122 
123  return $asset;
124 
125  }//end getAsset()
126 
127 
150  function getLinks($assetid, $link_types, $type_code='', $strict_type_code=TRUE, $side_of_link='major', $sort_by=NULL, $dependant=NULL, $exclusive=NULL)
151  {
152  // there are no links away from the shadow asset (ie:questions)
153  if (!is_numeric($assetid)) {
154  $links = Array();
155  if ($side_of_link == 'minor') {
156  $return_link = FALSE;
157 
158  if ($type_code == '') {
159  // not fussed what we're getting, so return me
160  $return_link = TRUE;
161  } else if ($strict_type_code) {
162  // strict type code check
163  $return_link = ($type_code == $this->type());
164  } else {
165  $return_link = (in_array($this->type(), $GLOBALS['SQ_SYSTEM']->am->getTypeDescendants($type_code, TRUE)));
166  }
167 
168  if ($return_link) {
169  $links[] = Array(
170  'linkid' => 0,
171  'majorid' => $this->id,
172  'minorid' => $this->id.':'.$assetid,
173  'major_type_code' => $this->type(),
174  'value' => '',
175  'link_type' => SQ_LINK_TYPE_2,
176  'is_dependant' => TRUE,
177  'is_exclusive' => FALSE,
178  'sort_order' => 0,
179  'locked' => 0,
180  );
181  }
182  }
183 
184  return $links;
185  }//end if assetid is not numeric
186 
187  $links = Array();
188  $new_sort_order = 0;
189 
190  // are we getting our bodycopy and/or nested forms (if they all exist)?
191  $real_type_codes = Array(
192  'bodycopy' => SQ_LINK_TYPE_2 | SQ_LINK_TYPE_3,
193  'simple_form' => SQ_LINK_TYPE_2,
194  );
195 
196  foreach ($real_type_codes as $real_type_code => $allowed_link_types) {
197  if ($type_code == '') {
198  // not fussed what we're getting, so return me
199  $get_type = TRUE;
200  } else if ($strict_type_code) {
201  $get_type = ($type_code == $real_type_code);
202  } else {
203  // specific type code set, non-strict check
204  $get_type = (in_array($real_type_code, $GLOBALS['SQ_SYSTEM']->am->getTypeDescendants($type_code, TRUE)));
205  }
206 
207  // we are getting this type?
208  if ($get_type) {
209  $links_query = $GLOBALS['SQ_SYSTEM']->am->generateGetLinksQuery($assetid, $link_types & $allowed_link_types, $real_type_code, FALSE);
210  $type_links = NULL;
211  try {
212  $query = MatrixDAL::preparePdoQuery(implode(' ', $links_query['sql_array']));
213 
214  foreach($links_query['bind_vars'] as $bind_var => $bind_value) {
215  MatrixDAL::bindValueToPdo($query, $bind_var, $bind_value);
216  }
217  $type_links = MatrixDal::executePdoAssoc($query);
218  } catch (Exception $e) {
219  throw new Exception($e->getMessage());
220  }
221 
222  foreach (array_keys($type_links) as $key) {
223  $type_links[$key]['sort_order'] = $new_sort_order;
224  $links[] = $type_links[$key];
225  $new_sort_order++;
226  }
227  }
228  }
229 
230  // but we also need question shadow asset links
231  if ($link_types & SQ_LINK_TYPE_2) {
232  $questions = $this->attr('questions');
233 
234  // keep a cache of asset type codes if we are checking on a non-strict
235  // type code, to stop us calling getTypeDescendants() all the time
236  // (not needed if strict type check or if not fussed)
237  $get_question_types = Array();
238 
239  foreach ($questions as $questionid => $data) {
240  if ($type_code == '') {
241  // not fussed what we're getting, so return me
242  $get_question = TRUE;
243  } else if ($strict_type_code) {
244  // strict type code check
245  $get_question = ($type_code == $data['type_code']);
246  } else {
247  // if we've already cached whether this question type is to be
248  // returned, then we don't need to look it up again
249  if (isset($get_question_types[$data['type_code']])) {
250  $get_question = $get_question_types[$data['type_code']];
251  $get_question_types[$data['type_code']] = $get_question;
252  } else {
253  $get_question = (in_array($data['type_code'], $GLOBALS['SQ_SYSTEM']->am->getTypeDescendants($type_code, TRUE)));
254  }
255  }
256 
257  if ($get_question) {
258  $links[] = Array(
259  'linkid' => 0,
260  'majorid' => $this->id,
261  'minorid' => $this->id.':q'.$questionid,
262  'minor_type_code' => $data['type_code'],
263  'value' => '',
264  'link_type' => SQ_LINK_TYPE_2,
265  'is_dependant' => TRUE,
266  'is_exclusive' => FALSE,
267  'sort_order' => $new_sort_order,
268  'locked' => 0,
269  );
270  }
271  $new_sort_order++;
272  }//end foreach
273  }//end if
274 
275  if (is_null($sort_by)) $sort_by = 'sort_order';
276 
277  uasort($links, create_function('$a,$b','return $a["'.$sort_by.'"] > $b["'.$sort_by.'"];'));
278 
279  return $links;
280 
281  }//end getLinks()
282 
283 
290  function getAssetMapLinks()
291  {
292  $new_sort_order = 0;
293  $old_links = $this->getLinks($this->id, SQ_SC_LINK_BACKEND_NAV);
294  $links = Array();
295  while (!empty($old_links)) {
296  array_push($links, array_shift($old_links));
297  }
298 
299  $questions = $this->attr('questions');
300 
301  foreach (array_keys($links) as $i) {
302 
303  $link = &$links[$i];
304  if ($link['minor_type_code'] == 'bodycopy') {
305  unset($links[$i]);
306  continue;
307  }
308 
309  if ($link['minor_type_code'] == 'simple_form') {
310  unset($links[$i]);
311  continue;
312  }
313 
314  // mould it all to the asset map's liking
315  $link['url'] = '';
316  $link['path'] = '';
317  $link['num_kids'] = 0;
318  $link['accessible'] = 1;
319 
320  $link['assetid'] = $link['minorid'];
321  $link['type_code'] = $link['minor_type_code'];
322  $link['linkid'] = $link['majorid'].':'.$link['minorid'];
323 
324  $questionid = str_replace($this->id.':q', '', $link['assetid']);
325 
326  // make name and short name the same
327  $link['name'] = $questions[$questionid]['attributes']['name'];
328  $link['short_name'] = $link['name'];
329 
330  // make the status the same as the form's one
331  $link['status'] = $this->status;
332 
333  unset($link['minor_type_code']);
334  unset($link['majorid']);
335  unset($link['minorid']);
336  unset($link['value']);
337  unset($link['is_exclusive']);
338 
339  }//end foreach
340 
341  return $links;
342 
343  }//end getAssetMapLinks()
344 
345 
360  function getParents($shadowid, $type_code='', $strict_type_code=TRUE)
361  {
362  // basically get the parents of the section, and add itself in the
363  $ret_val = $GLOBALS['SQ_SYSTEM']->am->generateGetParentsQuery($this->id, $type_code, $strict_type_code);
364  if (empty($ret_val)) return Array();
365 
366  $queried_parents = NULL;
367  try {
368  $query = MatrixDAL::preparePdoQuery(implode(' ', $ret_val['sql_array']));
369  foreach ($ret_val['bind_vars'] as $bind_var => $bind_value) {
370  MatrixDAL::bindValueToPdo($query, $bind_var, $bind_value);
371  }
372 
373  $queried_parents = MatrixDAL::executePdoAll($query);
374  } catch (Exception $e) {
375  throw new Exception($e->getMessage());
376  }//end
377 
378  $parents = Array();
379 
380  foreach ($queried_parents as $queried_parent) {
381  $parents[$queried_parent['majorid']] = $queried_parent['type_code'];
382  }
383 
384  $parents[$this->id] = $this->type();
385 
386  return $parents;
387 
388  }//end getParents()
389 
390 
411  function getChildren($assetid, $type_code='', $strict_type_code=TRUE, $dependant=NULL, $sort_by=NULL)
412  {
413  // no shadow assets have children in this asset
414  if (!is_numeric($assetid)) return Array();
415 
416  if (!is_array($type_code)) {
417  if (empty($type_code)) {
418  $type_code = Array();
419  } else {
420  $type_code = Array($type_code);
421  }
422  }
423 
424  $children = Array();
425 
426  // this is so we get the sections as we go
427  // have to do this all in here because calling asset manager will bring on a vicious loop
428  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
429  if (($asset instanceof Bridge) && ($assetid != $this->id)) {
430  $children = $asset->getChildren($assetid, $type_code, $strict_type_code, $dependant, $sort_by);
431  $this->forgetAsset($asset);
432  } else {
433  $ret_val = $GLOBALS['SQ_SYSTEM']->am->generateGetChildrenQuery($asset, $type_code, $strict_type_code, $dependant, $sort_by);
434  unset($asset);
435 
436 
437  if (!empty($ret_val)) {
438  $sql_array = $ret_val['sql_array'];
439  $bind_vars = $ret_val['bind_vars'];
440 
441  $result = NULL;
442  try {
443  $query = MatrixDAL::preparePdoQuery(implode(' ', $sql_array));
444  foreach ($bind_vars as $bind_var => $bind_value) {
445  MatrixDAL::bindValueToPdo($query, $bind_var, $bind_value);
446  }
447  $result = MatrixDal::executePdoGroupedAssoc($query);
448  } catch (Exception $e) {
449  throw new Exception($e->getMessage());
450  }
451 
452  $children = $result;
453  }
454  }
455 
456  // now questions
457  $entries = $this->attr('questions');
458  if (empty($type_code)) {
459  foreach ($entries as $questionid => $data) {
460  $children[$this->id.':q'.$questionid] = Array(Array('type_code' => $data['type_code']));
461  }
462  } else {
463  foreach ($type_code as $this_type_code) {
464  foreach ($entries as $questionid => $data) {
465  if ($strict_type_code) {
466  if ($data['type_code'] == $this_type_code) {
467  $children[$this->id.':q'.$questionid] = Array(Array('type_code' => $data['type_code']));
468  }
469  } else {
470  $type_desc = $GLOBALS['SQ_SYSTEM']->am->getTypeDescendants($this_type_code) + Array($this_type_code);
471  if (in_array($data['type_code'], $type_desc)) {
472  $children[$this->id.':q'.$questionid] = Array(Array('type_code' => $data['type_code']));
473  }
474  }
475  }
476  }
477  }
478 
479  if (!is_null($sort_by)) {
480  uasort($children, create_function('$a,$b','return $a["'.$sort_by.'"] > $b["'.$sort_by.'"]'));
481  }
482 
483  return $children;
484 
485  }//end getChildren()
486 
487 
498  function getLineageFromURL($assetid, $protocol, $url)
499  {
500  return Array();
501 
502  }//end getLineageFromURL()
503 
504 
505 //-- ASSET COMMON FUNCTIONS --//
506 
507 
518  function _getName($short_name=FALSE, $contextid=NULL)
519  {
520  // No context specified, using the current context
521  if ($contextid === NULL) {
522  $contextid = $GLOBALS['SQ_SYSTEM']->getContextId();
523  }//end if
524 
525  // Obtain the attribute value for Name from the specified Context
526  $values = $GLOBALS['SQ_SYSTEM']->am->getAttributeValuesByName('name', $this->type(), Array($this->id), $contextid);
527  if (empty($values) === TRUE) {
528  return parent::_getName($short_name, $contextid);
529  } else {
530  return $values[$this->id];
531  }
532 
533  }//end _getName()
534 
535 
543  function _getAllowedLinks()
544  {
545  $links = Array(
546  SQ_LINK_TYPE_2 => Array(
547  'bodycopy' => Array(
548  'card' => '1',
549  'exclusive' => FALSE,
550  ),
551  'simple_form' => Array(
552  'card' => 'M',
553  'exclusive' => FALSE,
554  ),
555  ),
556  SQ_LINK_TYPE_3 => Array(
557  'bodycopy' => Array(
558  'card' => '1',
559  'exclusive' => FALSE,
560  ),
561  ),
562  );
563  return $links;
564 
565  }//end _getAllowedLinks()
566 
567 
568 //-- QUESTION HANDLING FUNCTIONS --//
569 
570 
580  function createQuestion($type_code, $name=NULL)
581  {
582  $next_question = $this->attr('next_question');
583  $questions = $this->attr('questions');
584 
585  // if we weren't passed a name for some reason, set a default based on
586  // the 'next question' counter
587  if (is_null($name)) {
588  $name = 'Question '.$next_question;
589  }
590 
591  // set up the new question and bump the 'next question' counter
592  $questions[$next_question] = Array(
593  'type_code' => $type_code,
594  'name' => $name,
595  'sort_order' => count($questions),
596  'attributes' => Array(
597  'name' => $name,
598  ),
599  );
600 
601  $this->setAttrValue('questions', $questions);
602  $this->setAttrValue('next_question', $next_question + 1);
603 
604  // for system integrity purposes, acquire the lock on the new question
605  $GLOBALS['SQ_SYSTEM']->am->acquireLock($this->id.':q'.$next_question, 'all', $this->id, TRUE);
606  $GLOBALS['SQ_SYSTEM']->am->updateLock($this->id, 'all');
607 
608  return TRUE;
609 
610  }//end createQuestion()
611 
612 
621  function deleteQuestion($assetid)
622  {
623  list($sectionid, $shadowid) = explode(':q', $assetid);
624 
625  // make sure we can actually do something this
626  if ($sectionid != $this->id) {
627  // TRANSLATE: Get an error number for this
628  trigger_error('Cannot delete question '.$assetid.' from '.translate('asset_format', $this->_getName(), $this->id).' as it does not belong to this section', E_USER_WARNING);
629  return FALSE;
630  }
631 
632  $questions = $this->attr('questions');
633 
634  if (!isset($questions[$shadowid])) {
635  // TRANSLATE: Get an error number for this
636  trigger_error('Cannot delete question '.$assetid.' from '.translate('asset_format', $this->_getName(), $this->id).' as it does not exist', E_USER_WARNING);
637  return FALSE;
638  } else {
639  unset($questions[$shadowid]);
640  }
641 
642  $this->setAttrValue('questions', $questions);
643  return TRUE;
644 
645  }//end deleteQuestion()
646 
647 
656  function paintQuestion($assetid)
657  {
658  $q = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
659  echo $q->getHTMLField();
660 
661  }//end paintQuestion()
662 
663 
664 //-- FRONT-END PROCESSING FUNCTIONS --//
665 
666 
673  function process()
674  {
675  if (!isset($this->_is_processed)) {
676  $this->_errors = Array();
677  $this->_answers = Array();
678 
679  foreach ($this->attr('questions') as $shadowid => $data) {
680  // get the question
681  $assetid = $this->id.':q'.$shadowid;
682  $name = 'q'.$assetid;
683  $q = $GLOBALS['SQ_SYSTEM']->am->getAsset($assetid);
684  $q->populate($this);
685 
686  // set the value and check whether it's valid
687  if (isset($_POST[$name])) $q->setValue($_POST[$name]);
688  $valid = $q->hasValidValue();
689 
690  if (!$valid) $this->_errors = array_merge($this->_errors, $q->getErrors());
691 
692  $this->_answers[$assetid] = Array(
693  'name' => $data['name'],
694  'type_code' => $data['type_code'],
695  'value' => $q->getValue(),
696  'summary' => $q->getSummary(),
697  'extra_data' => $q->getExtraData(),
698  'is_error' => !$valid,
699  );
700 
701  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($q);
702  unset($q);
703 
704  }//end foreach question
705 
706  // Now, handle nested forms
707  foreach ($GLOBALS['SQ_SYSTEM']->am->getLinks($this->id, SQ_LINK_TYPE_2, 'simple_form', FALSE) as $link) {
708  $sectionid = $link['minorid'];
709  $s = $GLOBALS['SQ_SYSTEM']->am->getAsset($sectionid);
710 
711  $valid = $s->process();
712  if (!$valid) {
713  $this->_errors = array_merge($this->_errors, $s->getErrors());
714  }
715 
716  $this->_answers += array_merge($this->_answers, $s->getAnswers());
717 
718  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($s);
719  unset($s);
720  }
721 
722  $this->_is_processed = TRUE;
723  }//end if
724 
725  return empty($this->_errors);
726 
727  }//end process()
728 
729 
736  function getErrors()
737  {
738  return $this->_errors;
739 
740  }//end getErrors()
741 
742 
762  function getQuestions($include_nested=FALSE)
763  {
764  $am = $GLOBALS['SQ_SYSTEM']->am;
765  $questions = Array();
766 
767  $questions_raw = $this->attr('questions');
768  foreach ($questions_raw as $q_id => $question) {
769  $new_id = $this->id.':q'.$q_id;
770  $questions[$new_id] = $question;
771 
772  // clear out unnecessary info from the question info
773  unset($questions[$new_id]['attributes']);
774  }
775 
776  if ($include_nested) {
777  $nested_forms = $am->getLinks($this->id, SQ_SC_LINK_SIGNIFICANT, 'simple_form', FALSE);
778  foreach ($nested_forms as $link) {
779  $form = $am->getAsset($link['minorid']);
780  if (!is_null($form)) {
781  $questions = array_merge($questions, $form->getQuestions($include_nested));
782  $am->forgetAsset($form);
783  }
784  }
785  }
786 
787  return $questions;
788 
789  }//end getQuestions()
790 
791 
812  function getAnswers()
813  {
814  return $this->_answers;
815 
816  }//end getAnswers()
817 
818 
825  function getAnswerValues()
826  {
827  $answer_values = Array();
828  foreach ($this->_answers as $assetid => $data) {
829  $answer_values[$assetid] = $data['value'];
830  }
831  return $answer_values;
832 
833  }//end getAnswerValues()
834 
835 
843  {
844  $answer_values = Array();
845  foreach ($this->_answers as $assetid => $data) {
846  $answer_values[$assetid] = $data['summary'];
847  }
848  return $answer_values;
849 
850  }//end getAnswerSummaries()
851 
852 
860  {
861  $answer_values = Array();
862  foreach ($this->_answers as $assetid => $data) {
863  $answer_values[$assetid] = $data['extra_data'];
864  }
865  return $answer_values;
866 
867  }//end getAnswerExtraData()
868 
869 
870 //-- CLIENT-SIDE VALIDATION --//
871 
872 
886  function getClientSideJS()
887  {
888  ob_start();
889  ?>submission_errors = new Array();
890 
891  <?php
892  $init_code = ob_get_contents();
893  ob_end_clean();
894 
895  $code = '';
896 
897  $questions = $this->attr('questions');
898  foreach (array_keys($questions) as $key) {
899  $q = $GLOBALS['SQ_SYSTEM']->am->getAsset($this->id.':q'.$key);
900 
901  $q_code = $q->generateJSCode();
902  $code .= $q_code.(empty($q_code) ? '' : "\n");
903 
904  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($q);
905  unset($q);
906  }
907 
908  foreach ($GLOBALS['SQ_SYSTEM']->am->getLinks($this->id, SQ_LINK_TYPE_2, 'simple_form', FALSE) as $link) {
909  // get the section
910  $sectionid = $link['minorid'];
911  $s = $GLOBALS['SQ_SYSTEM']->am->getAsset($sectionid);
912  $section_questions = $s->attr('questions');
913 
914  foreach (array_keys($section_questions) as $key) {
915  $q = $GLOBALS['SQ_SYSTEM']->am->getAsset($s->id.':q'.$key);
916 
917  $q_code = $q->generateJSCode();
918  $code .= $q_code.(empty($q_code) ? '' : "\n");
919 
920  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($q);
921  unset($q);
922  }
923 
924  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($s);
925  unset($s);
926  }
927 
928  if (empty($code)) {
929  return '';
930  } else {
931  return $init_code.$code;
932  }
933 
934  }//end getClientSideJS()
935 
936 
944  {
945  $code = $this->getClientSideJS();
946  if (empty($code)) return '';
947 
948  ob_start();
949  ?>
950 <script type="text/javascript">
951 function beforeSubmit_<?php echo $this->getPrefix() ?>(form) {
952  <?php echo $code; ?>
953 
954  if (submission_errors.length > 0) {
955  var errors_list = "<?php echo translate('core_form_submission_errors'); ?>\n";
956  for(x in submission_errors) {
957  errors_list += submission_errors[x] + "\n";
958  }
959 
960  alert(errors_list);
961  return false;
962  } else {
963  return true;
964  }
965 }//end beforeSubmit_<?php echo $this->getPrefix() ?>()
966 </script>
967  <?php
968  $code = ob_get_contents();
969  ob_end_clean();
970 
971  return $code;
972 
973  }//end getClientSideFunction()
974 
975 
976 //-- KEYWORD PROVISION --//
977 
978 
989  function onRequestKeywords(&$broadcaster, $vars=Array())
990  {
991  $vars['keywords'] = isset($vars['keywords']) ? $vars['keywords'] : Array();
992  $keywords = Array();
993 
994  if ($this->isFormatBodycopyEnabled()) {
995  $keywords = $this->getDisplayKeywords('form_');
996  }
997 
998  $vars['keywords'] = array_merge($vars['keywords'], $keywords);
999 
1000  }//end onRequestKeywords()
1001 
1002 
1014  function getDisplayKeywords($prefix)
1015  {
1016  $questions = $this->attr('questions');
1017  $keywords = Array();
1018 
1019  foreach ($questions as $shadowid => $question) {
1020  $keywords[$prefix.$this->id.'_q'.$shadowid] = 'Question Field: '.ellipsisize($question['attributes']['name'], 30).' ('.$this->id.':q'.$shadowid.')';
1021  $keywords[$prefix.$this->id.'_q'.$shadowid.'_note'] = 'Question Note: '.ellipsisize($question['attributes']['name'], 30).' ('.$this->id.':q'.$shadowid.')';
1022  $keywords[$prefix.$this->id.'_q'.$shadowid.'_id'] = 'Question ID: '.ellipsisize($question['attributes']['name'], 30).' ('.$this->id.':q'.$shadowid.')';
1023  }
1024 
1025  foreach ($GLOBALS['SQ_SYSTEM']->am->getLinks($this->id, SQ_LINK_TYPE_2, 'simple_form', FALSE) as $link) {
1026  // get the section
1027  $sectionid = $link['minorid'];
1028  $s = $GLOBALS['SQ_SYSTEM']->am->getAsset($sectionid);
1029 
1030  $keywords += $s->getDisplayKeywords($prefix);
1031  $keywords[$prefix.$s->id.'_name'] = 'Nested Form Name: '.$s->name.' ('.$s->id.')';
1032 
1033  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($s);
1034  unset($s);
1035  }
1036 
1037  $keywords['submit_button'] = 'Submit Button';
1038  $keywords['reset_button'] = 'Reset Button';
1039  $keywords['form_errors'] = 'Form Errors';
1040 
1041  return $keywords;
1042 
1043  }//end getDisplayKeywords()
1044 
1045 
1057  function getResponseKeywords($prefix)
1058  {
1059  $questions = $this->attr('questions');
1060  $keywords = Array();
1061 
1062  foreach ($questions as $shadowid => $question) {
1063  $keywords[$prefix.$this->id.'_q'.$shadowid] = 'Summary: '.ellipsisize($question['attributes']['name'], 30).' ('.$this->id.':q'.$shadowid.')';
1064  $keywords[$prefix.$this->id.'_q'.$shadowid.'_raw'] = 'Raw Response: '.ellipsisize($question['attributes']['name'], 30).' ('.$this->id.':q'.$shadowid.')';
1065  }
1066 
1067  foreach ($GLOBALS['SQ_SYSTEM']->am->getLinks($this->id, SQ_LINK_TYPE_2, 'simple_form', FALSE) as $link) {
1068  // get the nested form
1069  $sectionid = $link['minorid'];
1070  $s = $GLOBALS['SQ_SYSTEM']->am->getAsset($sectionid);
1071 
1072  $keywords += $s->getResponseKeywords($prefix);
1073  $keywords[$prefix.$s->id.'_name'] = 'Nested Form Name: '.$s->name.' ('.$s->id.')';
1074 
1075  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($s);
1076  unset($s);
1077  }
1078 
1079  return $keywords;
1080 
1081  }//end getResponseKeywords()
1082 
1083 
1084 //-- KEYWORD REPLACEMENTS PROVISION --//
1085 
1086 
1099  {
1100  $questions = $this->attr('questions');
1101  $keywords = Array();
1102 
1103  foreach ($questions as $shadowid => $question) {
1104  // get the question
1105  $q = $GLOBALS['SQ_SYSTEM']->am->getAsset($this->id.':q'.$shadowid);
1106  $keywords[$prefix.$this->id.'_q'.$shadowid] = $q->getHtmlField();
1107  $keywords[$prefix.$this->id.'_q'.$shadowid.'_note'] = $q->attr('note');
1108  $keywords[$prefix.$this->id.'_q'.$shadowid.'_id'] = 'q'.$this->id.'_q'.$shadowid;
1109  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($q);
1110  unset($q);
1111  }
1112 
1113  foreach ($GLOBALS['SQ_SYSTEM']->am->getLinks($this->id, SQ_LINK_TYPE_2, 'simple_form', FALSE) as $link) {
1114  // get the nested form
1115  $sectionid = $link['minorid'];
1116  $s = $GLOBALS['SQ_SYSTEM']->am->getAsset($sectionid);
1117 
1118  $keywords += $s->getDisplayKeywordReplacements($prefix);
1119  $keywords[$prefix.$s->id.'_name'] = $s->name;
1120 
1121  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($s);
1122  unset($s);
1123  }
1124 
1125  // Submit Button, Reset Button, Form Errors
1126  ob_start();
1127  submit_button('submit_button', $this->attr('submit_button'));
1128  $submit_button = ob_get_contents();
1129  ob_end_clean();
1130 
1131  ob_start();
1132  reset_button('reset_button', $this->attr('reset_button'));
1133  $reset_button = ob_get_contents();
1134  ob_end_clean();
1135 
1136  $keywords['submit_button'] = $submit_button;
1137  $keywords['reset_button'] = $reset_button;
1138  $keywords['form_errors'] = implode('<br/>', $this->_errors);
1139 
1140  return $keywords;
1141 
1142  }//end getDisplayKeywordReplacement()
1143 
1144 
1157  {
1158  $questions = $this->attr('questions');
1159  $keywords = Array();
1160 
1161  foreach ($questions as $shadowid => $question) {
1162  $q = $GLOBALS['SQ_SYSTEM']->am->getAsset($this->id.':q'.$shadowid);
1163  $keywords[$prefix.$this->id.'_q'.$shadowid] = htmlentities($q->getSummary(), ENT_NOQUOTES, SQ_CONF_DEFAULT_CHARACTER_SET);
1164  $keywords[$prefix.$this->id.'_q'.$shadowid.'_raw'] = htmlentities($q->getValue(), ENT_NOQUOTES, SQ_CONF_DEFAULT_CHARACTER_SET);
1165  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($q);
1166  unset($q);
1167  }
1168 
1169  foreach ($GLOBALS['SQ_SYSTEM']->am->getLinks($this->id, SQ_LINK_TYPE_2, 'simple_form', FALSE) as $link) {
1170  // get the nested form
1171  $sectionid = $link['minorid'];
1172  $s = $GLOBALS['SQ_SYSTEM']->am->getAsset($sectionid);
1173 
1174  $keywords += $s->getResponseKeywordReplacements($prefix);
1175  $keywords[$prefix.$s->id.'_name'] = $s->name;
1176 
1177  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($s);
1178  unset($s);
1179  }
1180 
1181  return $keywords;
1182 
1183  }//end getResponseKeywordReplacement()
1184 
1185 
1186 //-- CUSTOM FORMAT BODYCOPY FUNCTIONS --//
1187 
1188 
1201  function createFormatBodycopy($enable_on_create=TRUE)
1202  {
1203  $_bodycopy_link = $GLOBALS['SQ_SYSTEM']->am->getLinks($this->id, SQ_LINK_TYPE_2 | SQ_LINK_TYPE_3, 'bodycopy', 'format');
1204  $bodycopy_link = reset($_bodycopy_link);
1205 
1206  // we already have a bodycopy link?!
1207  if ($bodycopy_link) {
1208  return FALSE;
1209  } else {
1210  $GLOBALS['SQ_SYSTEM']->am->includeAsset('bodycopy');
1211 
1212  $link_type = ($enable_on_create ? SQ_LINK_TYPE_2 : SQ_LINK_TYPE_3);
1213 
1214  $asset = new Bodycopy();
1215  $copy_link = Array(
1216  'asset' => &$this,
1217  'value' => 'format',
1218  'link_type' => $link_type,
1219  'is_dependant' => 1,
1220  'is_exclusive' => 1,
1221  );
1222 
1223  $asset->setAttrValue('name', 'Format Bodycopy');
1224  if (!$asset->create($copy_link)) return FALSE;
1225 
1226  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($asset);
1227  unset($asset);
1228  }
1229 
1230  return TRUE;
1231 
1232  }//end createFormatBodycopy()
1233 
1234 
1245  function &getFormatBodycopy($only_if_enabled=TRUE)
1246  {
1247  $asset = NULL;
1248 
1249  if ($only_if_enabled) {
1250  $link_types = SQ_LINK_TYPE_2;
1251  } else {
1252  $link_types = SQ_LINK_TYPE_2 | SQ_LINK_TYPE_3;
1253  }
1254 
1255  $tmp_bodycopy = $GLOBALS['SQ_SYSTEM']->am->getLinks($this->id, $link_types, 'bodycopy', 'format');
1256  $bodycopy_link = reset($tmp_bodycopy);
1257 
1258  if ($bodycopy_link) {
1259  $asset = $GLOBALS['SQ_SYSTEM']->am->getAsset($bodycopy_link['minorid'], 'bodycopy');
1260  }
1261 
1262  return $asset;
1263 
1264  }//end getFormatBodycopy()
1265 
1266 
1274  {
1275  $link_types = SQ_LINK_TYPE_2 | SQ_LINK_TYPE_3;
1276 
1277  $_bodycopy_link = $GLOBALS['SQ_SYSTEM']->am->getLinks($this->id, $link_types, 'bodycopy', 'format');
1278  $bodycopy_link = reset($_bodycopy_link);
1279 
1280  if ($bodycopy_link) {
1281  return ($bodycopy_link['link_type'] == SQ_LINK_TYPE_2);
1282  } else {
1283  return FALSE;
1284  }
1285 
1286 
1287  }//end isFormatBodycopyEnabled()
1288 
1289 
1299  function setUseFormatBodycopy($enabled)
1300  {
1301  $tmp_bodycopy = $GLOBALS['SQ_SYSTEM']->am->getLinks($this->id, SQ_LINK_TYPE_2 | SQ_LINK_TYPE_3, 'bodycopy', 'format');
1302  $bodycopy_link = reset($tmp_bodycopy);
1303 
1304  if (!$bodycopy_link) {
1305  // no bodycopy yet? If we're trying to set to disabled, then we don't
1306  // need to do anything - if not then we need to create it
1307  if ($enabled) {
1308  if (!$this->createFormatBodycopy()) return FALSE;
1309  }
1310  } else {
1311  // set link type to either TYPE_2 if enabled or TYPE_3 if disabled
1312  $new_link_type = ($enabled) ? SQ_LINK_TYPE_2 : SQ_LINK_TYPE_3;
1313  if ($bodycopy_link['link_type'] != $new_link_type) {
1314  $GLOBALS['SQ_SYSTEM']->am->updateLink($bodycopy_link['linkid'], $new_link_type);
1315  }
1316  }
1317 
1318  return TRUE;
1319 
1320  }//end setUseFormatBodycopy()
1321 
1322 
1323 //-- FORM SELF-PRINTING FUNCTIONS --//
1324 
1325 
1336  function printBody($print_form_tags=TRUE, $submit_buttons=TRUE, $form_action='', $print_js=TRUE)
1337  {
1338  // return custom bodycopy but ONLY if enabled
1339  $format_bodycopy = $this->getFormatBodycopy(TRUE);
1340 
1341  // default form action
1342  if (empty($form_action)) {
1343  $form_action = $_SERVER['PHP_SELF'];
1344  }
1345 
1346  // We need to print js function even if we are not printing the form here, as another form in higher level (if any) might wanna use it
1347  if ($print_js && $this->attr('client_side')) {
1348  $client_side = $this->getClientSideFunction('beforeSubmit_'.$this->getPrefix());
1349  $onsubmit = ' onSubmit="return beforeSubmit_'.$this->getPrefix().'(this)"';
1350  } else {
1351  $client_side = '';
1352  $onsubmit = '';
1353  }
1354  echo $client_side;
1355 
1356  if ($print_form_tags) {
1357  ?><form id="<?php echo $this->getPrefix() ?>" enctype="multipart/form-data" action="<?php echo $form_action; ?>" method="post"<?php echo $onsubmit; ?>><?php
1358  }
1359 
1360  // if format bodycopy enabled, print with that, otherwise print default
1361  if ($format_bodycopy) {
1362  $this->printCustomFormat($format_bodycopy);
1363  } else {
1364  $this->printDefaultFormat($submit_buttons);
1365  }
1366 
1367  if ($print_form_tags) {
1368  ?></form><?php
1369  }
1370 
1371  }//end printBody()
1372 
1373 
1382  function printDefaultFormat($submit_buttons=TRUE)
1383  {
1384  ?>
1385  <table>
1386  <?php foreach ($this->attr('questions') as $shadowid => $question) {
1387  $q = $GLOBALS['SQ_SYSTEM']->am->getAsset($this->id.':q'.$shadowid);
1388  $name = array_get_index($question['attributes'], 'name', '');
1389  $note = array_get_index($question['attributes'], 'note', '');
1390 
1391  $field = $q->getHTMLField();
1392  ?>
1393  <tr>
1394  <td><?php echo $name;
1395  echo ($note == '') ? '' : ('<br/><span style="font-size:0.8em">'.$note.'</span>'); ?></td>
1396  <td><?php echo $field; ?></td>
1397  </tr>
1398  <?php
1399  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($q);
1400  unset($q);
1401  }
1402 
1403  if ($submit_buttons) {
1404  ?>
1405  <tr><td style="text-align:center" colspan="2"><?php
1406  submit_button('submit_button', $this->attr('submit_button'));
1407  reset_button('reset_button', $this->attr('reset_button'));
1408  ?></td></tr>
1409  <?php }
1410  ?>
1411  </table>
1412  <?php
1413 
1414  }//end printDefaultFormat()
1415 
1416 
1425  function printCustomFormat(&$bodycopy)
1426  {
1427  $replacements = $this->getDisplayKeywordReplacement('form_');
1428  $bodycopy->setKeywordReplacements($replacements);
1429  $bodycopy->printBody();
1430 
1431  }//end printCustomFormat()
1432 
1433 
1434 //-- FORM STANDARD RECEIPT FUNCTIONS --//
1435 
1436 
1449  function printReceipt($html=TRUE, $include_form_info=TRUE)
1450  {
1451  $answers = Array();
1452 
1453  // include form info if asked for
1454  if ($include_form_info) {
1455  $form_info = Array();
1456  $lineage = $GLOBALS['SQ_SYSTEM']->am->getLineageFromURL();
1457  $lineage_names = Array();
1458  foreach ($lineage as $asset) {
1459  $lineage_names[] = $asset['name'];
1460  }
1461 
1462  $form_info[] = Array(
1463  'name' => 'Form Submitted',
1464  'value' => $this->name.' (Id: #'.$this->id.')',
1465  );
1466 
1467  $form_info[] = Array(
1468  'name' => 'Form URL',
1469  'value' => current_url(TRUE, TRUE),
1470  'html_value' => '<a href="'.current_url(TRUE, TRUE).'">'.current_url(TRUE, TRUE).'</a>',
1471  );
1472 
1473  $form_info[] = Array(
1474  'name' => 'Form Lineage',
1475  'value' => implode(' => ', $lineage_names),
1476  );
1477 
1478  $form_info[] = Array(
1479  'name' => 'Time of Submission',
1480  'value' => date('l, j F Y H:i:s \G\M\TO'),
1481  );
1482 
1483  if ($GLOBALS['SQ_SYSTEM']->userPublic()) {
1484  $form_info[] = Array(
1485  'name' => 'Submitted By',
1486  'value' => 'No logged in user',
1487  );
1488  } else {
1489  $user = $GLOBALS['SQ_SYSTEM']->user;
1490  $form_info[] = Array(
1491  'name' => 'Submitted By',
1492  'value' => $user->name.' (Id: #'.$user->id.')',
1493  );
1494  }
1495 
1496  // set max length equal to "time of submission" (we are getting the
1497  // max length of a question so the answers will align in the text
1498  // version)
1499  $max_name_length = 18;
1500  } else {
1501  $max_name_length = 0;
1502  }
1503 
1504  // gather questions
1505  foreach ($this->attr('questions') as $shadowid => $question) {
1506  $q = $GLOBALS['SQ_SYSTEM']->am->getAsset($this->id.':q'.$shadowid);
1507  $name = array_get_index($question['attributes'], 'name', '');
1508  $summary = $q->getSummary();
1509 
1510  $answers[] = Array(
1511  'name' => $name,
1512  'value' => $summary,
1513  );
1514  $max_name_length = max($max_name_length, strlen($name));
1515 
1516  $GLOBALS['SQ_SYSTEM']->am->forgetAsset($q);
1517  unset($q);
1518  }
1519 
1520  // now print the receipt
1521  if ($html) {
1522  ?>
1523  <table>
1524  <?php
1525  // only show form info if asked for
1526  if ($include_form_info) {
1527  ?>
1528  <tr><td colspan="2"><strong>Form Information</strong></td></tr>
1529  <?php foreach ($form_info as $form_info_item) {
1530  ?>
1531  <tr>
1532  <td valign="top"><ul><li><?php echo htmlspecialchars($form_info_item['name']); ?>:</li></ul></td>
1533  <td valign="top"><?php echo array_get_index($form_info_item, 'html_value', htmlspecialchars($form_info_item['value'])); ?></td>
1534  </tr>
1535  <?php
1536  }
1537  ?><tr><td colspan="2"><strong>Form Responses</strong></td></tr><?php
1538  }
1539  ?>
1540 
1541  <?php foreach ($answers as $answer) {
1542  ?>
1543  <tr>
1544  <td valign="top"><ul><li><?php echo htmlspecialchars($answer['name']); ?>:</li></ul></td>
1545  <td valign="top"><?php echo htmlspecialchars($answer['value']); ?></td>
1546  </tr>
1547  <?php }
1548  ?>
1549  </table>
1550  <?php
1551  } else {
1552 
1553  // only show form info if asked for
1554  if ($include_form_info) {
1555  echo '=== Form Information ==='."\n";
1556  foreach ($form_info as $form_info_item) {
1557  echo '* '.str_pad($form_info_item['name'], $max_name_length + 1).': '.$form_info_item['value']."\n";
1558  }
1559  echo "\n";
1560  echo '=== Form Responses ==='."\n";
1561  }
1562 
1563  foreach ($answers as $answer) {
1564  echo '* '.str_pad($answer['name'], $max_name_length + 1).': '.$answer['value']."\n";
1565  }
1566  }
1567 
1568  }//end printReceipt()
1569 
1570 
1580  function deleteAssetLink($linkid, $moving=FALSE)
1581  {
1582  return FALSE;
1583 
1584  }//end deleteAssetLink()
1585 
1586 
1608  function countLinks($assetid, $side_of_link='major', $link_types=0, $type_code='', $strict_type_code=TRUE, $ignore_linkid=0)
1609  {
1610  return 0;
1611 
1612  }//end countLinks()
1613 
1614 
1623  function getAssetMapAssetInfo($assetid)
1624  {
1625  return Array();
1626 
1627  }//end getAssetMapAssetInfo()
1628 
1629 
1630 }//end class
1631 
1632 
1633 ?>