Squiz Matrix  4.12.2
 All Data Structures Namespaces Functions Variables Pages
context_config.inc
1 <?php
18 require_once SQ_LIB_PATH.'/config/config.inc';
19 require_once SQ_LIB_PATH.'/html_form/html_form.inc';
20 
39 class Context_Config extends Config
40 {
41 
46  var $config_vars = Array(
47  // Proxy Options
48  'SQ_CONTEXT_DEFINITIONS' => Array('editable' => 1, 'default' => 'a:0:{}'),
49  );
50 
60  var $prefix = 'config_context_';
61 
62 
68  var $new_vars = NULL;
69 
70 
76  function __construct()
77  {
78  $this->config_vars['SQ_CONTEXT_DEFINITIONS']['default'] = serialize(Array('0' => Array('name' => 'Default Context')));
79 
80  parent::__construct();
81  $this->config_file = NULL;
82 
83  }//end constructor
84 
85 
98  function paintBackend(&$o)
99  {
100  $contexts = $this->load();
101  parent::paintBackend($o);
102 
103  $write_access = $this->writeAccess();
104  $class = get_class_lower($this);
105 
106  // Post variables
107  if ($write_access === TRUE) {
108  $current_context = array_get_index($_POST, $this->prefix.'selected');
109  if (!is_numeric($current_context)) {
110  // Don't let bad data get the better of this screen
111  $current_context = NULL;
112  } else {
113  $current_context = (int)$current_context;
114  }
115 
116  if ($current_context == NULL) {
117  // We can only be editing a context if we haven't selected one
118  // in the same page request.
119  $editing_context = array_get_index($_POST, $this->prefix.'editing');
120  if (!is_numeric($editing_context)) {
121  $editing_context = NULL;
122  } else {
123  $editing_context = (int)$editing_context;
124  }
125  }
126  } else {
127  // Can't have a "current context" while the screen is
128  // not locked!
129  $current_context = NULL;
130  }
131 
132  // Summary list of contexts
133  $o->openSection(translate($this->prefix.'list_of_contexts'));
134  $o->openRaw('');
135  $this->paintSummary($o, $contexts, $write_access, $current_context);
136  $o->closeRaw();
137  $o->sectionNote(translate($this->prefix.'note'));
138 
139  $o->closeSection();
140 
141  // Edit currently selected context (as selected through the post var)
142  if (($write_access === TRUE) && (is_null($current_context) === FALSE)) {
143  if (isset($contexts[$current_context]) === TRUE) {
144  $o->openSection(translate($this->prefix.'edit_selected_context'));
145  $this->paintSelectedContext($o, $contexts, $current_context);
146  $o->closeSection();
147  }
148  }
149 
150  if ($write_access) $o->commitButton('', TRUE);
151 
152  }//end paintBackend()
153 
154 
167  public function paintSummary(Backend_Outputter $o, Array $contexts, $write_access, $current_context=NULL)
168  {
169  ?>
170 <?php hidden_field($this->prefix.'selected', ''); ?>
171 <?php hidden_field($this->prefix.'deleted', ''); ?>
172 <table class="sq-backend-table" style="margin-bottom: 1em">
173  <colgroup>
174  <col width="60" />
175  <col width="20%" />
176  <col />
177  <col width="60" />
178  <col width="120" />
179  <col width="60" />
180  </colgroup>
181  <tbody>
182 <?php
183  // Keep a running tally of number of alternate
184  // contexts, so we can offer a default name to it
185  $alt_context_num = 0;
186 
187  // Make sure default context is up top, sort the
188  // rest by sort order
189  $default_context = Array(0 => $contexts[0]);
190  unset($contexts[0]);
191  uasort($contexts, create_function('$a,$b', 'return $a["sort_order"] - $b["sort_order"];'));
192  $contexts = $default_context + $contexts;
193 
194  foreach ($contexts as $contextid => $context) {
195  $context_name = array_get_index($context, 'name', '');
196  $context_errors = $this->_getContextErrors($context);
197  $condition_err_count = 0;
198 
199  if ($alt_context_num === 0) {
200 
201  ?>
202  <tr class="sq-table-row">
203  <td class="sq-backend-table-header-header" colspan="6">
204  <?php
205  echo translate($this->prefix.'default_name'); ?>
206  </td>
207  </tr>
208  <tr>
209  <th><?php echo translate('edit_question'); ?></th>
210  <th><?php echo translate($this->prefix.'context_name'); ?></th>
211  <th colspan="4"></th>
212  </tr>
213  <?php
214  }
215 
216  if ($current_context === (int)$contextid) {
217  $row_class = 'sq-table-row alt';
218  } else {
219  $row_class = 'sq-table-row';
220  }
221  ?>
222  <tr class="<?php echo $row_class; ?>">
223  <td class="sq-backend-table-cell" align="center"><?php
224  if (($write_access === TRUE) && ((int)$contextid !== $current_context)) { ?>
225  <p><a href="#" onclick="document.getElementById('<?php echo $this->prefix; ?>selected').value = <?php echo $contextid ?>; document.main_form.submit(); return false;"><?php echo trim(sq_get_icon(sq_web_path('lib').'/web/images/icons/edit_mode.png', 15, 15, translate($this->prefix.'edit_alt_text', $context_name), NULL, ' border="0"')); ?></a></p><?php
226  }
227  ?>
228  </td>
229  <td class="sq-backend-table-cell">
230  <strong><?php echo $context_name; ?></strong><?php
231  if ($contextid !== 0) {
232  hidden_field($this->prefix.'reorder[]', $contextid, ' id="'.$this->prefix.'reorder_'.$contextid.'"');
233  }
234  ?>
235  </td>
236  <td class="sq-backend-table-cell"><?php
237  if ($contextid === 0) {
238  echo translate($this->prefix.'default_explanation');
239  $valid = TRUE;
240  } else {
241  if ($context['at_least'] === NULL) {
242  echo translate($this->prefix.'table_all_description', count($context['conditions']));
243  } else {
244  echo translate($this->prefix.'table_at_least_description', $context['at_least'], count($context['conditions']));
245  }
246 
247  ?><ul>
248  <?php
249  $condition_text = $this->_getSummaryConditionList($context['conditions']);
250  foreach ($condition_text as $condition_id => $condition_text_item) {
251  ?><li><?php echo $condition_text_item;
252  $condition_errors = array_get_index($context_errors, $condition_id, Array());
253  if (count($condition_errors) > 0) {
254  $condition_err_count++;
255  ?><ul>
256  <?php
257  foreach ($condition_errors as $condition_error) {
258  ?><li class="sq-backend-warning"><?php echo $condition_error; ?></li><?php
259  }
260  ?></ul><?php
261  }
262  ?></li>
263  <?php
264  }
265 
266  $condition_level_errors = array_get_index($context_errors, 'condition', Array());
267  if (count($condition_level_errors) > 0) {
268  foreach ($context_level_errors as $context_level_error) {
269  ?><li class="sq-backend-warning"><?php echo $condition_level_error; ?></li><?php
270  }
271  }
272 
273 
274  ?></ul>
275  <?php
276  $context_level_errors = array_get_index($context_errors, 'context', Array());
277  if (count($context_level_errors) > 0) {
278  foreach ($context_level_errors as $context_level_error) {
279  ?><p class="sq-backend-warning"><?php echo $context_level_error; ?></p><?php
280  }
281  }
282 
283  if (count($context['conditions']) === 0) {
284  $valid = FALSE;
285  } else if ($context['at_least'] === NULL) {
286  $valid = (count($context_errors) === 0) ? TRUE : FALSE;
287  } else {
288  $valid = ((count($context['conditions']) - $condition_err_count) >= $context['at_least']) ? TRUE : FALSE;
289  }
290 
291  if ($condition_err_count > 0) {
292  if ($valid === TRUE) {
293  ?><p><?php
294  echo translate($this->prefix.'invalid_cond_but_still_valid');
295  ?></p><?php
296  } else {
297  ?><p class="sq-backend-warning"><?php
298  echo translate($this->prefix.'not_enough_valid_cond_to_be_valid');
299  ?></p><?php
300  }
301  }
302  }
303  ?>
304  </td>
305  <td class="sq-backend-table-cell" align="center"><?php
306  // valid icon
307  // Context is valid IF:
308  // ALL conditions are required, and no context errors,
309  // AT LEAST <x> conditions are required, and
310  // there are at least that many valid conditions.
311  if ($valid) {
312  echo trim(sq_get_icon(sq_web_path('lib').'/web/images/tick.gif', 15, 15, translate($this->prefix.'valid_alt_text', $context_name), NULL, ' border="0"'));
313  } else {
314  echo trim(sq_get_icon(sq_web_path('lib').'/web/images/cross.gif', 15, 15, translate($this->prefix.'not_valid_alt_text', $context_name), NULL, ' border="0"'));
315  }
316  ?>
317  </td>
318  <td class="sq-backend-table-cell" align="center"><?php
319  // reorder link
320  if ($write_access === TRUE) {
321  if ($alt_context_num > 1) {
322  ?><a href="#" onclick="return false;" class="reorder-up"><?php echo trim(sq_get_icon(sq_web_path('lib').'/web/images/icons/up_arrow.png', 15, 15, translate($this->prefix.'reorder_up_alt_text', $context_name), NULL, ' border="0"')); ?></a><?php
323  } else {
324  ?><img src="<?php echo sq_web_path('lib'); ?>/web/images/blank.gif" width="15" height="15" border="0" /><?php
325  }
326  ?> <?php
327  if (($contextid !== 0) && ($alt_context_num < count($contexts) - 1)) {
328  ?><a href="#" onclick="return false;" class="reorder-down"><?php echo trim(sq_get_icon(sq_web_path('lib').'/web/images/icons/down_arrow.png', 15, 15, translate($this->prefix.'reorder_down_alt_text', $context_name), NULL, ' border="0"')); ?></a><?php
329  } else {
330  ?><img src="<?php echo sq_web_path('lib'); ?>/web/images/blank.gif" width="15" height="15" border="0" /><?php
331  }
332  }
333  ?>
334  </td>
335  <td class="sq-backend-table-cell" align="center"><?php
336  // delete link
337  if (($write_access === TRUE) && ($contextid !== 0) && (($contextid !== $current_context))) {
338  ?><p><a href="#" onclick="if (confirm('<?php echo str_replace("\n", '\\n', translate($this->prefix.'delete_warning', $context_name)); ?>') == true) { document.getElementById('<?php echo $this->prefix; ?>deleted').value = <?php echo $contextid ?>; document.main_form.submit(); } return false;"><?php echo trim(sq_get_icon(sq_web_path('lib').'/web/images/icons/delete.png', 15, 15, translate($this->prefix.'delete_alt_text', $context_name), NULL, ' border="0"')); ?></a></p><?php
339 
340  }
341  ?>
342  </td>
343  </tr><?php
344  if ($alt_context_num === 0) {
345  // Print the alternate headers row here, because it should always be
346  // printed even if no alternates exist (see "add new alternate"
347  // row below)
348  ?>
349  <tr class="sq-table-row">
350  <td class="sq-backend-table-header-header" colspan="6">
351  <?php
352  echo translate($this->prefix.'alternate_contexts'); ?>
353  </td>
354  </tr><?php
355  if (count($contexts) > 1) {
356  // print second header row for alternate contexts
357  ?>
358  <tr class="sq-table-row">
359  <th><?php echo translate('edit_question'); ?></th>
360  <th><?php echo translate($this->prefix.'context_name'); ?></th>
361  <th><?php echo translate($this->prefix.'context_details'); ?></th>
362  <th style="text-align: center"><?php echo translate('valid_question'); ?></th>
363  <th style="text-align: center"><?php echo translate('reorder_question'); ?></th>
364  <th style="text-align: center"><?php echo translate('delete_question'); ?></th>
365  </tr><?php
366  } else {
367  // No alternate contexts - don't print header; instead print message
368  // and a "lock screen to add" message if screen unlocked
369  ?>
370  <tr class="sq-table-row">
371  <td class="sq-backend-table-cell"></td>
372  <td class="sq-backend-table-cell" colspan="5"><?php echo translate($this->prefix.'no_alternate_contexts'); ?></td>
373  </tr><?php
374  }
375  }
376 
377  $alt_context_num++;
378  }
379 
380  if ($write_access) {
381  // Add a new alternate context
382  ?>
383  <tr class="sq-table-row">
384  <td class="sq-backend-table-header-header" colspan="6">
385  <?php
386  echo translate($this->prefix.'new_alternate_context'); ?>
387  </td>
388  </tr>
389  <tr>
390  <td></td>
391  <td colspan="2"><?php
392  if ($write_access) {
393  ob_start();
394  check_box($this->prefix.'new_alternate_context', '1', FALSE, 'document.getElementById("'.$this->prefix.'new_alternate_context_name").disabled = !this.checked; if (this.checked == true) { document.getElementById("'.$this->prefix.'new_alternate_context_name").focus() };');
395  $check_box = ob_get_clean();
396  ob_start();
397  text_box($this->prefix.'new_alternate_context_name', '', 20, 0, FALSE, ' disabled="disabled"');
398  $text_box = ob_get_clean();
399  echo translate($this->prefix.'new_alternate_context_line', $check_box, $text_box);
400  } else {
401  ?><br/><?php
402  echo translate($this->prefix.'lock_to_add_alternate');
403  }
404  ?>
405  </td>
406  <td colspan="3"></td>
407  </tr><?php
408  }
409  ?>
410  </tbody>
411 </table><?php
412 
413  // paint a hidden field for re-ordering
414  echo $this->_getReorderJS();
415  $o->addOnLoad('ContextConfig.setup();');
416 
417  }//end paintSummmary()
418 
419 
430  protected function _getReorderJS()
431  {
432  ob_start();
433  ?>
434  <script type="text/javascript">
435  /* <![CDATA[ */
436  ContextConfig = {
437  moveUp: function(link) {
438  row = link.parentNode.parentNode;
439  switch_row = row.previousSibling;
440 
441  while ((switch_row.nodeType != 1) || (switch_row.nodeName.toLowerCase() != 'tr')) {
442  switch_row = switch_row.previousSibling;
443  }
444 
445  row_tds = row.getElementsByTagName('td');
446  switch_row_tds = switch_row.getElementsByTagName('td');
447  for (var i = 0; i < row_tds.length; i++) {
448  // Only reorder when it's not the "reorder" column
449  if (row_tds[i].innerHTML.indexOf('class="reorder-') === -1) {
450  var temp = switch_row_tds[i].innerHTML;
451  switch_row_tds[i].innerHTML = row_tds[i].innerHTML;
452  row_tds[i].innerHTML = temp;
453  }
454  }
455 
456  var temp_style = row.className;
457  row.className = switch_row.className;
458  switch_row.className = temp_style;
459  },
460 
461  moveDown: function(link) {
462  row = link.parentNode.parentNode;
463  switch_row = row.nextSibling;
464 
465  while ((switch_row.nodeType != 1) || (switch_row.nodeName.toLowerCase() != 'tr')) {
466  switch_row = switch_row.nextSibling;
467  }
468 
469  row_tds = row.getElementsByTagName('td');
470  switch_row_tds = switch_row.getElementsByTagName('td');
471  for (var i = 0; i < row_tds.length; i++) {
472  // Only reorder when it's not the "reorder" column
473  if (row_tds[i].innerHTML.indexOf('class="reorder-') === -1) {
474  var temp = switch_row_tds[i].innerHTML;
475  switch_row_tds[i].innerHTML = row_tds[i].innerHTML;
476  row_tds[i].innerHTML = temp;
477  }
478  }
479 
480  var temp_style = row.className;
481  row.className = switch_row.className;
482  switch_row.className = temp_style;
483  },
484 
485  setup: function() {
486  var self = this;
487  var a_tags = document.getElementsByTagName('a');
488  for (var i = 0; i < a_tags.length; i++) {
489  a_tag = a_tags[i];
490  if (a_tag.className == 'reorder-up') {
491  a_tag.onclick = function(event) {
492  self.moveUp(this);
493  return false;
494  }
495  } else if (a_tag.className == 'reorder-down') {
496  a_tag.onclick = function(event) {
497  self.moveDown(this);
498  return false;
499  }
500  }
501  }
502  }
503  };
504 
505  /* ]]> */
506  </script>
507  <?php
508  $js = ob_get_clean();
509  return $js;
510 
511  }//end _getReorderJS()
512 
513 
525  protected function _getSummaryConditionList($conditions)
526  {
527  $condition_text = Array();
528 
529  foreach ($conditions as $condition_id => $condition_details) {
530  $options = $condition_details['options'];
531 
532  switch ($condition_details['type']) {
533  case 'accept-language':
534  $locales = $this->_getAcceptLanguageOptions();
535  $condition_text[$condition_id] = translate($this->prefix.'summary_cond_accept-language', $locales[$options['language']], number_format($options['min_q'], 1));
536  break;
537 
538  case 'header':
539  $translate_suffix = ((int)$options['match_logic'] === 1 ? '' : '!').$options['match_type'];
540  $case_sensitive_text = ((int)($options['case_sensitive']) === 1 ? '' : 'not_').'case_sensitive';
541  $condition_text[$condition_id] = translate($this->prefix.'summary_cond_header_'.$translate_suffix, $options['header_name'], $options['match_value'], translate($case_sensitive_text));
542  break;
543 
544  case 'get':
545  case 'post':
546  $translate_suffix = ((int)$options['match_logic'] === 1 ? '' : '!').$options['match_type'];
547  $case_sensitive_text = ((int)($options['case_sensitive']) === 1 ? '' : 'not_').'case_sensitive';
548  $condition_text[$condition_id] = translate($this->prefix.'summary_cond_'.$condition_details['type'].'_'.$translate_suffix, $options['var_name'], $options['match_value'], translate($case_sensitive_text));
549  break;
550 
551  case 'url':
552  $translate_suffix = ((int)$options['match_logic'] === 1 ? '' : '!').$options['match_type'];
553  $condition_text[$condition_id] = translate($this->prefix.'summary_cond_url_'.$translate_suffix, $options['match_value']);
554  break;
555 
556  case 'port':
557  $translate_suffix = ($options['match_type'] === 'is' ? '' : '_!');
558  $condition_text[$condition_id] = translate($this->prefix.'summary_cond_port'.$translate_suffix, $options['match_value']);
559  break;
560 
561  case 'secure':
562  $translate_suffix = ($options['match_value'] === 1 ? '' : '_!');
563  $condition_text[$condition_id] = translate($this->prefix.'summary_cond_secure'.$translate_suffix);
564  break;
565  }
566  }
567 
568  return $condition_text;
569 
570  }//end _getSummaryConditionList()
571 
572 
601  protected function _getContextErrors($context)
602  {
603  $context_errors = Array();
604 
605  if (count($context['conditions']) < 1) {
606  $context_errors['context'][] = translate($this->prefix.'context_has_no_conditions');
607  } else if ((is_numeric($context['at_least']) === TRUE) && ($context['at_least'] > count($context['conditions']))) {
608  $context_errors['context'][] = translate($this->prefix.'context_at_least_too_many', $context['at_least'], count($context['conditions']));
609  } else {
610  foreach ($context['conditions'] as $condition_id => $condition) {
611  $condition_type = $condition['type'];
612  $condition_options = $condition['options'];
613 
614  switch ($condition_type) {
615  case 'url':
616  if ($condition_options['match_value'] === '') {
617  $context_errors[$condition_id][] = translate($this->prefix.'error_cond_url_no_match_value');
618  }
619  break;
620 
621  case 'header':
622  if ($condition_options['header_name'] === '') {
623  $context_errors[$condition_id][] = translate($this->prefix.'error_cond_header_no_header_name');
624  }
625  if ($condition_options['match_value'] === '') {
626  $context_errors[$condition_id][] = translate($this->prefix.'error_cond_header_no_match_value');
627  }
628  break;
629 
630  case 'get':
631  case 'post':
632  if ($condition_options['var_name'] === '') {
633  $context_errors[$condition_id][] = translate($this->prefix.'error_cond_no_request_var_name');
634  }
635  if ($condition_options['match_value'] === '') {
636  $context_errors[$condition_id][] = translate($this->prefix.'error_cond_request_var_no_match_value');
637  }
638  break;
639  }
640  }
641  }
642 
643  return $context_errors;
644 
645  }//end _getContextErrors()
646 
647 
661  public function paintSelectedContext(Backend_Outputter $o, Array $contexts, $current_context)
662  {
663  $o->openField(translate('name'));
664  text_box($this->prefix.'name', array_get_index($contexts[$current_context], 'name', ''));
665  hidden_field($this->prefix.'editing', (string)$current_context);
666  $o->closeField();
667 
668  if ($current_context !== 0) {
669  if (empty($contexts[$current_context]['at_least']) === FALSE) {
670  $at_least = $contexts[$current_context]['at_least'];
671  } else {
672  $at_least = NULL;
673  }
674 
675  if (empty($contexts[$current_context]['conditions']) === FALSE) {
676  $conditions = $contexts[$current_context]['conditions'];
677  } else {
678  $conditions = Array();
679  }
680 
681  $o->openField(translate($this->prefix.'minimum_matches'));
682  $list_options = Array(
683  'at_least' => translate('at_least'),
684  'all' => translate('all'),
685  );
686 
687  if ($at_least === NULL) {
688  $default_option = 'all';
689  $at_least = '';
690  } else {
691  $default_option = 'at_least';
692  if (is_numeric($at_least) === FALSE) {
693  $at_least = '';
694  }
695  }
696 
697  ob_start();
698  combo_box($this->prefix.'min', $list_options, FALSE, $default_option, 0, ' onchange="if (this.value == \'all\') document.getElementById(\''.$this->prefix.'at_least\').value = \'\';"');
699  $cb = ob_get_clean();
700  ob_start();
701  int_text_box($this->prefix.'at_least', $at_least, FALSE, 3, 1, NULL, 2, FALSE, FALSE, ' onchange="if (this.value != \'\') document.getElementById(\''.$this->prefix.'minimum_matches\').selectedIndex = 0;');
702  $tb = ob_get_clean();
703  echo translate($this->prefix.'minimum_matches_interface', $cb, $tb);
704  ?>
705  <?php
706  $o->closeField();
707 
708  $o->openField(translate('conditions'));
709  $this->_paintConditionsList($o, $conditions);
710  $o->closeField();
711 
712  $option_types = Array(
713  'accept-language' => translate($this->prefix.'type_accept-language'),
714  'header' => translate($this->prefix.'type_header'),
715  'url' => translate($this->prefix.'type_url'),
716  'port' => translate($this->prefix.'type_port'),
717  'secure' => translate($this->prefix.'type_secure'),
718  'get' => translate($this->prefix.'type_get'),
719  'post' => translate($this->prefix.'type_post'),
720  );
721 
722  $o->openField(translate('new_condition_question'));
723  ?><p><?php
724  ob_start();
725  check_box($this->prefix.'new_condition', '1', FALSE, 'document.getElementById("'.$this->prefix.'new_condition_type").disabled = !this.checked; if (this.checked == true) { document.getElementById("'.$this->prefix.'new_condition_type").focus() };');
726  $check_box = ob_get_clean();
727  ob_start();
728  combo_box($this->prefix.'new_condition_type', $option_types, FALSE, Array(), 0, ' disabled="disabled"');
729  $combo_box = ob_get_clean();
730  echo translate($this->prefix.'new_condition_line', $check_box, $combo_box);
731  $o->closeField();
732  }
733 
734  }//end paintSelectedContext()
735 
736 
746  protected function _paintConditionsList(Backend_Outputter $o, $conditions)
747  {
748  ?>
749  <table class="sq-backend-table" style="margin-bottom: 1em">
750  <colgroup>
751  <col width="10%" />
752  <col />
753  <col width="60" />
754  </colgroup>
755  <tbody>
756  <tr class="sq-table-row">
757  <th><?php echo translate($this->prefix.'condition_type'); ?></th>
758  <th><?php echo translate($this->prefix.'condition_details'); ?></th>
759  <th style="text-align: center"><?php echo translate('delete_question'); ?></th>
760  </tr><?php
761  foreach ($conditions as $condition_id => &$condition_options) {
762  ?>
763  <tr><?php
764  $condition_type = $conditions[$condition_id]['type'];
765  ?>
766  <td><p><strong><?php echo translate($this->prefix.'type_'.$condition_type); ?></strong></p></td><?php
767  ?>
768  <td><?php
769  $this->_paintCondition($o, $conditions, $condition_id);
770  ?></td>
771  <td align="center"><p><strong><?php check_box($this->prefix.'condition_delete['.$condition_id.']', '1', FALSE); ?></strong></p></td><?php
772  ?>
773  </tr><?php
774  }
775 
776  ?>
777  </tbody>
778  </table>
779  <?php
780 
781  }//end _paintConditionsList()
782 
783 
794  protected function _paintCondition(Backend_Outputter $o, $conditions, $condition_id)
795  {
796  $condition_type = $conditions[$condition_id]['type'];
797  $condition_details = $conditions[$condition_id]['options'];
798 
799  switch ($condition_type) {
800  case 'accept-language':
801  $locales = $this->_getAcceptLanguageOptions();
802  ?>
803  <ul>
804  <li><?php
805  $current_language = $condition_details['language'];
806  ob_start();
807  combo_box($this->prefix.$condition_id.'_language', $locales, FALSE, Array($current_language));
808  $language_cb = ob_get_clean();
809  echo translate($this->prefix.'type_accept-language_param_language', $language_cb);
810  ?></li>
811  <li><?php
812  ob_start();
813  // Get current q-value and make sure it's in the bounds of 0.0..1.0
814  $min_q = $condition_details['min_q'];
815  $min_q = min($min_q, 1);
816  $min_q = max($min_q, 0);
817 
818  // If 0 or 1, show it to the user with one decimal place
819  // (ie. 0.0 or 1.0), similar to HTTP definition's examples.
820  if ((float)$min_q == (int)$min_q) {
821  $min_q = number_format($min_q, 1);
822  }
823  text_box($this->prefix.$condition_id.'_min_q', $min_q, 5, 0, FALSE, ' onblur="val = parseFloat(this.value); if (isNaN(val)) {this.value = \'\'; } else {val = Math.min(Math.max(val, 0), 1); if (val == parseInt(this.value)) {this.value = parseInt(this.value) + \'.0\'; } }"');
824  $min_q_box = ob_get_clean();
825  echo translate($this->prefix.'type_accept-language_param_min_q', $min_q_box);
826  ?>
827  </li>
828  </ul>
829  <p><?php
830  echo translate($this->prefix.'type_accept-language_param_explanation');
831  ?></p><?php
832  break;
833 
834  case 'header':
835  ?>
836  <ul>
837  <li><?php
838  $header_name = $condition_details['header_name'];
839  $match_logic = $condition_details['match_logic'];
840  $match_type = $condition_details['match_type'];
841  $match_value = $condition_details['match_value'];
842  $case_sensitive = $condition_details['case_sensitive'];
843 
844  $logic_options = Array(
845  1 => translate($this->prefix.'type_header_option_1'),
846  0 => translate($this->prefix.'type_header_option_0'),
847  );
848 
849  $type_options = Array(
850  'exists' => translate($this->prefix.'type_header_option_exists'),
851  'exact' => translate($this->prefix.'type_header_option_exact'),
852  'begins' => translate($this->prefix.'type_header_option_begins'),
853  'ends' => translate($this->prefix.'type_header_option_ends'),
854  'contains' => translate($this->prefix.'type_header_option_contains'),
855  );
856 
857  ob_start();
858  text_box($this->prefix.$condition_id.'_header_name', $header_name, 30);
859  $header_tb = ob_get_clean();
860  ob_start();
861  combo_box($this->prefix.$condition_id.'_match_logic', $logic_options, FALSE, Array($match_logic));
862  $logic_cb = ob_get_clean();
863  ob_start();
864  combo_box($this->prefix.$condition_id.'_match_type', $type_options, FALSE, Array($match_type));
865  $type_cb = ob_get_clean();
866  ob_start();
867  text_box($this->prefix.$condition_id.'_match_value', $match_value, 30);
868  $value_tb = ob_get_clean();
869  ob_start();
870  check_box($this->prefix.$condition_id.'_case_sensitive', '1', $case_sensitive);
871  $case_ch = ob_get_clean();
872  echo translate($this->prefix.'type_header_param', $header_tb, $logic_cb, $type_cb, $value_tb, $case_ch);
873  ?>
874  </li>
875  </ul>
876  <p><?php
877  echo translate($this->prefix.'type_header_param_explanation');
878  ?></p><?php
879  break;
880 
881  case 'get':
882  case 'post':
883  ?>
884  <ul>
885  <li><?php
886  $var_name = $condition_details['var_name'];
887  $match_logic = $condition_details['match_logic'];
888  $match_type = $condition_details['match_type'];
889  $match_value = $condition_details['match_value'];
890  $case_sensitive = $condition_details['case_sensitive'];
891 
892  $logic_options = Array(
893  1 => translate($this->prefix.'type_header_option_1'),
894  0 => translate($this->prefix.'type_header_option_0'),
895  );
896 
897  $type_options = Array(
898  'exists' => translate($this->prefix.'type_header_option_exists'),
899  'exact' => translate($this->prefix.'type_header_option_exact'),
900  'begins' => translate($this->prefix.'type_header_option_begins'),
901  'ends' => translate($this->prefix.'type_header_option_ends'),
902  'contains' => translate($this->prefix.'type_header_option_contains'),
903  );
904 
905  ob_start();
906  text_box($this->prefix.$condition_id.'_var_name', $var_name, 30);
907  $var_tb = ob_get_clean();
908  ob_start();
909  combo_box($this->prefix.$condition_id.'_match_logic', $logic_options, FALSE, Array($match_logic));
910  $logic_cb = ob_get_clean();
911  ob_start();
912  combo_box($this->prefix.$condition_id.'_match_type', $type_options, FALSE, Array($match_type));
913  $type_cb = ob_get_clean();
914  ob_start();
915  text_box($this->prefix.$condition_id.'_match_value', $match_value, 30);
916  $value_tb = ob_get_clean();
917  ob_start();
918  check_box($this->prefix.$condition_id.'_case_sensitive', '1', $case_sensitive);
919  $case_ch = ob_get_clean();
920  echo translate($this->prefix.'type_'.$condition_type.'_param', $var_tb, $logic_cb, $type_cb, $value_tb, $case_ch);
921  ?>
922  </li>
923  </ul>
924  <p><?php
925  echo translate($this->prefix.'type_header_param_explanation');
926  ?></p><?php
927  break;
928 
929  case 'url':
930  ?>
931  <ul>
932  <li><?php
933  $match_logic = $condition_details['match_logic'];
934  $match_type = $condition_details['match_type'];
935  $match_value = $condition_details['match_value'];
936 
937  $logic_options = Array(
938  1 => translate($this->prefix.'type_url_option_1'),
939  0 => translate($this->prefix.'type_url_option_0'),
940  );
941 
942  $type_options = Array(
943  'exact' => translate($this->prefix.'type_url_option_exact'),
944  'begins' => translate($this->prefix.'type_url_option_begins'),
945  'ends' => translate($this->prefix.'type_url_option_ends'),
946  'contains' => translate($this->prefix.'type_url_option_contains'),
947  );
948 
949  ob_start();
950  combo_box($this->prefix.$condition_id.'_match_logic', $logic_options, FALSE, Array($match_logic));
951  $logic_cb = ob_get_clean();
952  ob_start();
953  combo_box($this->prefix.$condition_id.'_match_type', $type_options, FALSE, Array($match_type));
954  $type_cb = ob_get_clean();
955  ob_start();
956  text_box($this->prefix.$condition_id.'_match_value', $match_value, 30);
957  $value_tb = ob_get_clean();
958  echo translate($this->prefix.'type_url_param', $logic_cb, $type_cb, $value_tb);
959  ?>
960  </li>
961  </ul>
962  <p><?php
963  echo translate($this->prefix.'type_url_param_explanation');
964  ?></p><?php
965  break;
966 
967  case 'port':
968  ?>
969  <ul>
970  <li><?php
971  $match_type = $condition_details['match_type'];
972  $port = $condition_details['match_value'];
973  $options = Array(
974  'is' => translate($this->prefix.'type_port_option_1'),
975  'is_not' => translate($this->prefix.'type_port_option_0'),
976  );
977  ob_start();
978  combo_box($this->prefix.$condition_id.'_match_type', $options, FALSE, Array($match_type));
979  $cb = ob_get_clean();
980  ob_start();
981  int_text_box($this->prefix.$condition_id.'_match_value', $port, FALSE, 7, 0, 65535);
982  $tb = ob_get_clean();
983  echo translate($this->prefix.'type_port_param', $cb, $tb);
984  ?>
985  </li>
986  </ul>
987  <p><?php
988  echo translate($this->prefix.'type_port_param_explanation');
989  ?></p><?php
990  break;
991 
992  case 'secure':
993  ?>
994  <ul>
995  <li><?php
996  $match = $condition_details['match_value'];
997  $options = Array(
998  0 => translate($this->prefix.'type_secure_option_0'),
999  1 => translate($this->prefix.'type_secure_option_1'),
1000  );
1001  ob_start();
1002  combo_box($this->prefix.$condition_id.'_match_value', $options, FALSE, Array($match));
1003  $cb = ob_get_clean();
1004  echo translate($this->prefix.'type_secure_param', $cb);
1005  ?>
1006  </li>
1007  </ul>
1008  <p><?php
1009  echo translate($this->prefix.'type_secure_param_explanation');
1010  ?></p><?php
1011  break;
1012  }
1013 
1014  }//end _paintCondition()
1015 
1016 
1027  public function processSelectedContext(Backend_Outputter $o, Array $contexts, $current_context)
1028  {
1029 
1030  }//end processSelectedContext()
1031 
1032 
1043  public function paintMatchOrder(Backend_Outputter $o, Array $match_order, $write_access)
1044  {
1045 
1046  }//end paintMatchOrder()
1047 
1048 
1058  public function processMatchOrder(Backend_Outputter $o, Array $match_order)
1059  {
1060 
1061  }//end processMatchOrder()
1062 
1063 
1073  public function processBackend(Backend_Outputter $o)
1074  {
1075  if (empty($_POST['sq_lock_release_manual']) === FALSE) {
1076  $this->releaseLock();
1077  }
1078 
1079  $contexts = $this->load();
1080  $context_names = Array();
1081  foreach ($contexts as $key => $value){
1082  $context_names[] = $value['name'];
1083  }
1084 
1085  $save_required = FALSE;
1086  $saved = FALSE;
1087 
1088  $current_context = NULL;
1089  $editing_context = NULL;
1090  $new_key = NULL;
1091 
1092  // Don't release the lock unless we tell you to
1093  unset($_POST['sq_lock_release']);
1094 
1095  if ($this->writeAccess() === TRUE) {
1096  $class = get_class_lower($this);
1097 
1098  // Post variables
1099  $deleted_context = array_get_index($_POST, $this->prefix.'deleted');
1100  if (is_numeric($deleted_context) === TRUE) {
1101  // Deleting a context outright
1102  unset($contexts[$deleted_context]);
1103  $active_context = $GLOBALS['SQ_SYSTEM']->getContextId();
1104  if ((int)$deleted_context === (int)$active_context) {
1105  $GLOBALS['SQ_SYSTEM']->restoreContext();
1106  $new_alternate_context = $GLOBALS['SQ_SYSTEM']->getAlternateContext();
1107  $GLOBALS['SQ_SYSTEM']->changeContext($new_alternate_context);
1108  $_SESSION[SQ_SESSION_SANDBOX_INDEX]['SQ_ALTERNATE_CONTEXT_ID'] = $new_alternate_context;
1109  }
1110  $save_required = TRUE;
1111 
1112  // Release the lock
1113  $_POST['sq_lock_release'] = TRUE;
1114  } else {
1115  // Post variables
1116  $current_context = array_get_index($_POST, $this->prefix.'selected');
1117  if (!is_numeric($current_context)) {
1118  // Don't let bad data get the better of this screen
1119  $current_context = NULL;
1120  } else {
1121  $current_context = (int)$current_context;
1122  }
1123 
1124  if ($current_context === NULL) {
1125  // We can only be editing a context if we haven't selected one
1126  // in the same page request.
1127  $editing_context = array_get_index($_POST, $this->prefix.'editing');
1128  if (!is_numeric($editing_context)) {
1129  $editing_context = NULL;
1130  } else {
1131  $editing_context = (int)$editing_context;
1132  }
1133  } else {
1134  $editing_context = NULL;
1135  }
1136 
1137  // Have the contexts been reordered in the interface?
1138  $reorder_post = array_get_index($_POST, $this->prefix.'reorder', Array());
1139  if (empty($reorder_post) === FALSE) {
1140  foreach ($reorder_post as $new_sort_order => $order_contextid) {
1141  if ((int)$contexts[$order_contextid]['sort_order'] !== (int)$new_sort_order) {
1142  $contexts[$order_contextid]['sort_order'] = $new_sort_order;
1143  $save_required = TRUE;
1144  }
1145  }
1146  }
1147 
1148  // This screen doesn't fulfil the usual rules for config saving because
1149  // of its complexity - usually we need POST vars like
1150  // $_POST['context_config']['SQ_CONTEXT_DEFINITIONS'] or similar.
1151  // So build them here before letting parent process the backend.
1152 
1153  if ($current_context === NULL) {
1154  if ((int)array_get_index($_POST, $this->prefix.'new_alternate_context', '0') === 1) {
1155  $new_name = trim(array_get_index($_POST, $this->prefix.'new_alternate_context_name', ''));
1156 
1157  if ($new_name === '' || in_array($new_name, $context_names)) {
1158  trigger_localised_error('CTX0005', E_USER_WARNING);
1159  } else {
1160  // Creating a new context - include the new name
1161  $new_key = MatrixDAL::executeOne('core', 'seqNextVal', Array('seqName' => 'sq_ctx_id_seq'));
1162  $new_sort_order = count($contexts);
1163  $contexts[$new_key] = Array(
1164  'name' => array_get_index($_POST, $this->prefix.'new_alternate_context_name', ''),
1165  'conditions' => Array(),
1166  'at_least' => NULL,
1167  'sort_order' => $new_sort_order,
1168  );
1169 
1170  // Allow the new key to flow through to the editing interface,
1171  // so the user can edit the new context
1172  $_POST[$this->prefix.'selected'] = $new_key;
1173  $save_required = TRUE;
1174  }
1175  }
1176  }
1177 
1178  if (($current_context === NULL) && ($editing_context !== NULL)) {
1179  // Editing a currently selected context
1180  $new_name = trim(array_get_index($_POST, $this->prefix.'name', ''));
1181 
1182  // If the new name is blank or already exists, refuse to change it, but allow
1183  // the rest of the editing to continue
1184  if ($new_name === '' || ($new_name != $contexts[$editing_context]['name'] && in_array($new_name, $context_names))) {
1185  trigger_localised_error('CTX0006', E_USER_NOTICE, $contexts[$editing_context]['name']);
1186  } else {
1187  $contexts[$editing_context]['name'] = $new_name;
1188  }
1189 
1190  if ($editing_context !== 0) {
1191  if (array_get_index($_POST, $this->prefix.'min') === 'all') {
1192  $at_least = NULL;
1193  } else {
1194  $at_least = array_get_index($_POST, $this->prefix.'at_least', 1);
1195  }
1196  $contexts[$editing_context]['at_least'] = $at_least;
1197 
1198  $deleted_conditions = array_get_index($_POST, $this->prefix.'condition_delete', Array());
1199  foreach ($deleted_conditions as $condition_id => $value) {
1200  unset($contexts[$editing_context]['conditions'][$condition_id]);
1201  }
1202 
1203  foreach ($contexts[$editing_context]['conditions'] as $condition_id => &$condition_value) {
1204  $this->_processCondition($condition_id, $condition_value['type'], $condition_value['options']);
1205  }
1206 
1207  // We are adding a new condition
1208  $new_condition_flag = array_get_index($_POST, $this->prefix.'new_condition', '0');
1209  if ((bool)$new_condition_flag === TRUE) {
1210  $new_condition_type = array_get_index($_POST, $this->prefix.'new_condition_type');
1211  $new_condition = Array(
1212  'type' => $new_condition_type,
1213  );
1214 
1215  switch ($new_condition_type) {
1216  case 'accept-language':
1217  // Defaults for accept-language header:
1218  // - Language not selected (REQUIRED to be valid)
1219  // - Minimum q-value of 0.0 (ie. language will match at any quality)
1220  $new_condition['options'] = Array(
1221  'language' => 'en',
1222  'min_q' => 0,
1223  );
1224  break;
1225 
1226  case 'header':
1227  // Defaults for 'other' header:
1228  // - Header name not specified (REQUIRED to be valid)
1229  // - Exact match to an empty string
1230  $new_condition['options'] = Array(
1231  'header_name' => '',
1232  'match_logic' => '1',
1233  'match_type' => 'exact',
1234  'match_value' => '',
1235  'case_sensitive' => '1',
1236  );
1237  break;
1238 
1239  case 'get':
1240  case 'post':
1241  // Defaults for 'other' header:
1242  // - Header name not specified (REQUIRED to be valid)
1243  // - Exact match to an empty string
1244  $new_condition['options'] = Array(
1245  'var_name' => '',
1246  'match_logic' => '1',
1247  'match_type' => 'exact',
1248  'match_value' => '',
1249  'case_sensitive' => '1',
1250  );
1251  break;
1252 
1253  case 'url':
1254  // Defaults for match by URL:
1255  // - Match value not specified (REQUIRED to be valid)
1256  // - Exact match by default
1257  $new_condition['options'] = Array(
1258  'match_logic' => '1',
1259  'match_type' => 'exact',
1260  'match_value' => '',
1261  );
1262  break;
1263 
1264  case 'port':
1265  // Match on port defaults to matching on port 80
1266  $new_condition['options'] = Array(
1267  'match_type' => 'is',
1268  'match_value' => 80,
1269  );
1270  break;
1271 
1272  case 'secure':
1273  // Match on secure: defaults to force secure
1274  $new_condition['options'] = Array(
1275  'match_value' => 1,
1276  );
1277  break;
1278 
1279  }//end switch on condition type
1280 
1281  $contexts[$editing_context]['conditions'][] = $new_condition;
1282 
1283  }//end if new condition is being created
1284 
1285  }//end if context being edited is not default
1286 
1287  $save_required = TRUE;
1288 
1289  }//end if editing context is not null
1290 
1291  }//end if deleted context is not null
1292 
1293 
1294  // This page cannot work properly with the default behaviour
1295  // of redirecting on save (usually done since define()'d constants
1296  // cannot be redefined). So we save a copy of the new vars
1297  // in save() and re-use them in paintBackend().
1298  //
1299  // The copied code (from parent::processBackend()) exists so we can
1300  // still give a correct TRUE/FALSE indication from save(), since
1301  // this normally determines whether it redirects or not.
1302  if (empty($_POST['process_form']) === FALSE) {
1303  if ($save_required === TRUE) {
1304  $vars = Array(
1305  'contexts' => $contexts,
1306  );
1307  $saved = $this->save($vars);
1308  }
1309  }
1310  }//end if write access permitted
1311 
1312  if (empty($_POST['sq_lock_release']) === FALSE) {
1313  $this->releaseLock();
1314  }
1315 
1316  // If we still have a lock, refresh it
1317  $this->updateLock();
1318 
1319  // if there is no lock currently and we want it
1320  if (empty($_POST['sq_lock_acquire']) === FALSE) {
1321  $this->acquireLock();
1322  }
1323 
1324  // If we are in the middle of editing a context, ensure it is still
1325  // selected - unless we created a new alternate context
1326  if (($editing_context !== NULL) && ($current_context === NULL) && ($new_key === NULL)) {
1327  $_POST[$this->prefix.'selected'] = $editing_context;
1328  }
1329 
1330  return $saved;
1331 
1332  }//end processBackend()
1333 
1334 
1346  protected function _processCondition($condition_id, $condition_type, &$condition_options)
1347  {
1348  switch ($condition_type) {
1349  case 'accept-language':
1350  $locales = $this->_getAcceptLanguageOptions();
1351  $new_language = array_get_index($_POST, $this->prefix.$condition_id.'_language', '');
1352  if (isset($locales[$new_language]) === FALSE) {
1353  trigger_localised_error('CTX0008', E_USER_NOTICE, $new_language);
1354  } else {
1355  $condition_options['language'] = $new_language;
1356  }
1357 
1358  $new_q_value = array_get_index($_POST, $this->prefix.$condition_id.'_min_q');
1359  if (is_numeric($new_q_value) === TRUE) {
1360  $new_q_value = (float)$new_q_value;
1361  if ($new_q_value > 1.0) {
1362  trigger_localised_error('CTX0009', E_USER_NOTICE, $new_q_value);
1363  $new_q_value = 1.0;
1364  }
1365  if ($new_q_value < 0.0) {
1366  trigger_localised_error('CTX0010', E_USER_NOTICE, $new_q_value);
1367  $new_q_value = 0.0;
1368  }
1369  $condition_options['min_q'] = $new_q_value;
1370  }
1371 
1372  break;
1373 
1374  case 'header':
1375  $condition_options['header_name'] = array_get_index($_POST, $this->prefix.$condition_id.'_header_name', '');
1376  $condition_options['case_sensitive'] = array_get_index($_POST, $this->prefix.$condition_id.'_case_sensitive', 0);
1377  $condition_options['match_logic'] = array_get_index($_POST, $this->prefix.$condition_id.'_match_logic', 1);
1378  $condition_options['match_type'] = array_get_index($_POST, $this->prefix.$condition_id.'_match_type', 'exact');
1379  $condition_options['match_value'] = array_get_index($_POST, $this->prefix.$condition_id.'_match_value', '');
1380  break;
1381 
1382  case 'get':
1383  case 'post':
1384  $condition_options['var_name'] = array_get_index($_POST, $this->prefix.$condition_id.'_var_name', '');
1385  $condition_options['case_sensitive'] = array_get_index($_POST, $this->prefix.$condition_id.'_case_sensitive', 0);
1386  $condition_options['match_logic'] = array_get_index($_POST, $this->prefix.$condition_id.'_match_logic', 1);
1387  $condition_options['match_type'] = array_get_index($_POST, $this->prefix.$condition_id.'_match_type', 'exact');
1388  $condition_options['match_value'] = array_get_index($_POST, $this->prefix.$condition_id.'_match_value', '');
1389  break;
1390 
1391  case 'url':
1392  $condition_options['match_logic'] = array_get_index($_POST, $this->prefix.$condition_id.'_match_logic', 1);
1393  $condition_options['match_type'] = array_get_index($_POST, $this->prefix.$condition_id.'_match_type', 'exact');
1394  $condition_options['match_value'] = array_get_index($_POST, $this->prefix.$condition_id.'_match_value', '');
1395  break;
1396 
1397  case 'port':
1398  $condition_options['match_type'] = array_get_index($_POST, $this->prefix.$condition_id.'_match_type', 1);
1399  $condition_options['match_value'] = array_get_index($_POST, $this->prefix.$condition_id.'_match_value', 80);
1400  break;
1401 
1402  case 'secure':
1403  $condition_options['match_value'] = array_get_index($_POST, $this->prefix.$condition_id.'_match_value', 0);
1404  break;
1405 
1406  }//end switch on condition type
1407 
1408  }//end _processCondition()
1409 
1410 
1416  public function load()
1417  {
1418  $contexts = $GLOBALS['SQ_SYSTEM']->getAllContexts(TRUE);
1419 
1420  // Remove the intervening '0' since the context ID is unique;
1421  // also unserialise conditions where needed
1422  // use PHP 5 assign-value-by-ref trick
1423  if (isset($contexts[0]) === FALSE) {
1424  $contexts[0] = Array(
1425  'name' => 'Default Context',
1426  'at_least' => NULL,
1427  'conditions' => NULL,
1428  'sort_order' => NULL,
1429  );
1430  }
1431 
1432  return $contexts;
1433 
1434  }//end load()
1435 
1436 
1453  function save($vars, $backup_existing=FALSE)
1454  {
1455  if ($this->writeAccess() === FALSE) {
1456  return FALSE;
1457  }
1458 
1459  // Cheat method to emulate getCol()
1460  $existing_contextids = array_keys(MatrixDAL::executeGrouped('core', 'getAllContextIDs', Array()));
1461  $current_contextids = array_keys(array_get_index($vars, 'contexts', Array()));
1462 
1463  $new_contextids = array_diff($current_contextids, $existing_contextids);
1464  $deleted_contextids = array_diff($existing_contextids, $current_contextids);
1465  $updated_contextids = array_intersect($current_contextids, $existing_contextids);
1466 
1467  $GLOBALS['SQ_SYSTEM']->changeDatabaseConnection('db2');
1468  $GLOBALS['SQ_SYSTEM']->doTransaction('BEGIN');
1469 
1470  $ok = TRUE;
1471 
1472  foreach ($new_contextids as $new_contextid) {
1473  try {
1474  $context =& $vars['contexts'][$new_contextid];
1475  $bind_vars = Array(
1476  'contextid' => $new_contextid,
1477  'name' => $context['name'],
1478  'conditions' => serialize($context['conditions']),
1479  'at_least' => $context['at_least'],
1480  'sort_order' => $context['sort_order'],
1481  );
1482  MatrixDAL::executeQuery('core', 'createContext', $bind_vars);
1483 
1484  } catch (DALException $e) {
1485  // Cannot insert context due to DB error.
1486  // It's not fatal from a PHP point of view - it is for
1487  // this processing though, so send a warning and break out
1488  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
1489  trigger_localised_error('CTX0001', E_USER_ERROR, $bind_vars['name'], $e->getMessage());
1490  exit(1);
1491 
1492  }//end try
1493 
1494  }//end foreach - new contexts
1495 
1496  if ($ok === TRUE) {
1497  foreach ($updated_contextids as $updated_contextid) {
1498  try {
1499  $context =& $vars['contexts'][$updated_contextid];
1500  $bind_vars = Array(
1501  'contextid' => $updated_contextid,
1502  'name' => $context['name'],
1503  'conditions' => serialize($context['conditions']),
1504  'at_least' => $context['at_least'],
1505  'sort_order' => $context['sort_order'],
1506  );
1507  MatrixDAL::executeQuery('core', 'updateContext', $bind_vars);
1508 
1509  } catch (DALException $e) {
1510  // Cannot update context due to DB error.
1511  // It's not fatal from a PHP point of view - it is for
1512  // this processing though, so send a warning and break out
1513  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
1514  trigger_localised_error('CTX0002', E_USER_ERROR, $bind_vars['name'], $e->getMessage());
1515  exit(1);
1516 
1517  }//end try
1518 
1519  }//end foreach - updated contexts
1520 
1521  }//end if
1522 
1523  // delete the condemned contexts all in one go
1524  if (($ok === TRUE) && (count($deleted_contextids) > 0)) {
1525  try {
1526  $bind_vars = Array(
1527  'contextids' => $deleted_contextids,
1528  );
1529  MatrixDAL::executeQuery('core', 'deleteContexts', $bind_vars);
1530 
1531  } catch (DALException $e) {
1532  // Cannot delete context(s) due to DB error,
1533  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
1534  if (count($deleted_contextids) === 1) {
1535  $deleted_contextid = $deleted_contextids[0];
1536  trigger_localised_error('CTX0003', E_USER_ERROR, $deleted_contextid, $e->getMessage());
1537  } else {
1538  trigger_localised_error('CTX0004', E_USER_ERROR, count($deleted_contextids), $e->getMessage());
1539  }
1540  exit(1);
1541 
1542  }//end try
1543 
1544  }//end if
1545 
1546  foreach ($new_contextids as $new_contextid) {
1547  if ($GLOBALS['SQ_SYSTEM']->insertContextData($new_contextid) === FALSE) {
1548  // ??? Presuming here that above function will throw error, perhaps fatal
1549  exit(1);
1550  }
1551  }
1552 
1553  foreach ($deleted_contextids as $deleted_contextid) {
1554  if ($GLOBALS['SQ_SYSTEM']->deleteContextData($deleted_contextid) === FALSE) {
1555  // ??? Presuming here that above function will throw error, perhaps fatal
1556  exit(1);
1557  }
1558  }
1559 
1560  if ($ok) {
1561  $GLOBALS['SQ_SYSTEM']->doTransaction('COMMIT');
1562  } else {
1563  $GLOBALS['SQ_SYSTEM']->doTransaction('ROLLBACK');
1564  }
1565 
1566  $GLOBALS['SQ_SYSTEM']->restoreDatabaseConnection();
1567 
1568  return $ok;
1569 
1570  }//end save()
1571 
1572 
1578  protected function _getAcceptLanguageOptions()
1579  {
1580  static $options = NULL;
1581 
1582  if (empty($options) === TRUE) {
1583  include SQ_FUDGE_PATH.'/standards_lists/languages.inc';
1584  include SQ_FUDGE_PATH.'/standards_lists/locales.inc';
1585  // Remove locales that are variations of other ones (eg.
1586  // for Euro support), often signified by a "@"
1587  foreach (array_keys($standards_lists_locales) as $locale_code) {
1588  $matches = preg_match('/^([a-zA-Z\_\-]+)$/', $locale_code);
1589  if ($matches === 0) {
1590  unset($standards_lists_locales[$locale_code]);
1591  }
1592  }
1593  $overlap = array_intersect($standards_lists_languages, $standards_lists_locales);
1594 
1595  foreach ($overlap as $code => $language) {
1596  if(isset($standards_lists_languages[$code])) {
1597  $standards_lists_languages[$code] = translate('non_localised_variation', $language);
1598  }
1599  }
1600 
1601  $options = $standards_lists_locales + $standards_lists_languages;
1602  ksort($options);
1603 
1604  }
1605 
1606  return $options;
1607 
1608  }//end _getAcceptLanguageOptions()
1609 
1610 }//end class
1611 
1612 ?>