18 require_once dirname(__FILE__).
'/../../metadata_field/metadata_field_edit_fns.inc';
41 parent::__construct();
65 require_once SQ_LIB_PATH.
'/html_form/html_form.inc';
68 $value_components = $asset->
attr(
'value_components');
71 if (is_null($value_str)) {
78 if ($asset->
attr(
'multiple')) {
83 $value = explode(
'; ', $value);
87 if ($enable_default) {
88 echo
'<span id="'.$prefix.
'_field">';
91 $display_type = $asset->
attr(
'display_type');
93 $hierarchy_options = $hierarchy->_params[
'options'];
97 $hierarchy->value = $value;
98 $hierarchy_sort = $hierarchy->_params[
'sort'];
99 $hierarchy_structure = $hierarchy->_params[
'structure'];
101 $hier_sort = (isset($hierarchy_sort) && $hierarchy_sort>=0) ? $hierarchy_sort :
'0';
102 $hier_structure = (isset($hierarchy_structure) && $hierarchy_structure) ? $hierarchy_structure : FALSE;
104 if ($enable_default) {
105 $hierarchy->_edit_params[
'extras'] =
'onclick="document.getElementById(\''.$prefix.
'_default\').checked = false;"';
107 $hierarchy->_edit_params[
'extras'] .=
' disabled="disabled"';
109 echo
'<span id="'.$prefix.
'_field">';
114 $options = $hierarchy->_params[
'options'];
117 $hierarchy->_params[
'options'] = $options;
119 $hierarchy->paint($prefix, FALSE);
122 $level_titles = $asset->
attr(
'level_titles');
124 if (!is_array($value)) {
125 $value = explode(
'; ', $value);
129 if (!$enable_default) {
130 $show_default_box = FALSE;
133 $show_default_box = TRUE;
135 $show_default_box = FALSE;
138 $this->
paintDrillDownView($hierarchy_options, $value, $level_titles, $show_default_box, explode(
'; ', $asset->
attr(
'default')), $prefix);
141 if (!((is_array($value) && empty($value)) || (is_string($value) && $value ==
''))) {
142 if (!is_array($value)) $value = Array($value);
144 foreach ($value as $option) {
145 if (isset($hierarchy_options[$option])) {
146 $value_output .= $hierarchy_options[$option].
'; ';
149 echo trim($value_output,
'; ');
153 if ($enable_default) {
158 echo
' ';
162 $default_keys = explode(
'; ', $asset->
attr(
'default'));
163 $default_selected = Array();
165 $default_key_values = Array();
166 $default_values = Array();
167 $non_default_keys = Array();
168 foreach ($hierarchy_options as $key => $hierarchy_option) {
169 if (in_array($key, $default_keys)) {
170 $default_key_values[] =
"'".addslashes($key).
"'";
171 $default_values[] =
"'".addslashes($hierarchy_option).
"'";
173 $non_default_keys[] =
"'".addslashes($key).
"'";
176 $default_keys_expr =
'['.implode(
', ', $default_key_values).
']';
177 $default_values_expr =
'['.implode(
', ', $default_values).
']';
178 $non_default_keys_expr =
'['.implode(
', ', $non_default_keys).
']';
179 check_box($prefix.
'_default',
'1', $is_default,
"handleDefaultClickHierarchy(this, '$prefix', $default_keys_expr, $default_values_expr, $non_default_keys_expr, $display_type); ");
180 label(translate(
'use_default'), $prefix.
'_default');
181 $o->
addJsInclude(sq_web_path(
'data').
'/asset_types/metadata_field_hierarchy/js/metadata_field_hierarchy.js');
184 echo
' <em style="color: #666">('.strtolower(translate(
'default')).
')</em>';
189 if ($write_access && $print_cascade_values_option) {
190 echo
' ';
191 check_box($prefix.
'_cascade_value',
'1', FALSE);
192 label(translate(
'cascade_value'), $prefix.
'_cascade_value');
195 return $write_access;
213 if (!$asset->
attr(
'editable'))
return FALSE;
218 if (!empty($_POST[$prefix.
'_default'])) {
220 $new_value_str = NULL;
226 $value = (isset($_REQUEST[$prefix])) ? $_REQUEST[$prefix] :
'';
227 if (is_array($value)) $value = implode(
'; ', $value);
229 $hoptions = $hierarchy->_params[
'options'];
231 $hierarchy->value = $value;
233 $new_value_str = $value;
238 if (isset($_POST[$prefix.
'_cascade_value'])) {
239 $field_cascade_value = TRUE;
262 $hierarchy_sort = $asset->
attr(
'hier_sort');
264 $is_contextable = (boolean)$asset->
attr(
'is_contextable');
266 $contextid = $GLOBALS[
'SQ_SYSTEM']->getContextId();
267 $is_default_context = ($contextid === 0) ? TRUE : FALSE;
269 if ($is_contextable === TRUE) {
272 $hierarchy_options = $GLOBALS[
'SQ_SYSTEM']->am->getAttributeValuesByName(
'hierarchy_options',
'metadata_field_hierarchy', Array($asset->id), 0);
273 $hierarchy_options = unserialize($hierarchy_options[$asset->id]);
276 if (!empty($hierarchy_options)) {
278 <table
class=
"sq-backend-table">
280 <td
class=
"sq-backend-table-header"><?php echo translate(
'option_key'); ?></td>
281 <td
class=
"sq-backend-table-header"><?php echo translate(
'option_value'); ?></td>
283 if (($write_access === TRUE) && ($is_default_context === TRUE)) {
284 ?><td
class=
"sq-backend-table-header"><?php echo translate(
'delete_question'); ?></td><?php
290 foreach ($hierarchy_options as $option_key => $option_value) {
293 <td
class=
"sq-backend-table-cell">
295 if ($write_access === TRUE) {
296 if (($is_default_context === TRUE) || ($is_contextable === FALSE)) {
297 text_box($prefix.
'_options[key]['.$i.
']', $option_key, 20);
300 hidden_field($prefix.
'_options[key]['.$i.
']', $option_key);
307 <td
class=
"sq-backend-table-cell" align=
"left">
310 text_box($prefix.
'_options[val]['.$i.
']', $option_value, 20);
317 if (($write_access === TRUE) && (($is_default_context === TRUE) || ($is_contextable === FALSE))) {
319 <td
class=
"sq-backend-table-cell">
320 <?php check_box($prefix.
'_options[del]['.$i.
']', $option_key); ?>
334 echo translate(
'no_hierarchy_box_options');
338 if (($write_access === TRUE) && (($is_default_context === TRUE) || ($is_contextable === FALSE))) {
340 echo
'<b>'.translate(
'key').
'</b> ';
341 text_box($prefix.
'_new_key',
'');
342 echo
' <b>'.translate(
'value').
'</b> ';
343 text_box($prefix.
'_new_val',
'');
348 $sort = $asset->
attr(
'hier_sort');
349 $format = $asset->
attr(
'hier_structure');
351 if (!empty($hierarchy_options)) {
353 $o->
openField(translate(
'default_value'));
355 $default_hier->paint($prefix.
'_default', !$write_access);
361 if (!empty($hierarchy_options)) {
363 $display_type = $asset->
attr(
'display_type');
364 if (!$display_type) {
369 if (isset($preview_options) && !is_null($preview_options)) {
370 foreach ($preview_options as $key => $value) {
371 $preview_options[$key] = substr($value, 0, 100);
375 $preview_options = $hierarchy_options;
379 if (isset($preview_options) && !is_null($preview_options)) {
380 foreach ($preview_options as $key => $value) {
381 $preview_options[$key] = substr($value, 0, 100);
387 $preview_hierarchy->_params[
'options'] = $preview_options;
388 $preview_hierarchy->value =
'';
389 $preview_hierarchy->paint(
'some_name_not_used', FALSE);
392 $level_titles = $asset->
attr(
'level_titles');
393 $this->
paintDrillDownView($preview_options, Array(), $level_titles, FALSE, Array(), $prefix);
396 echo translate(
'no_hierarchy_box_options');
418 public function paintDrillDownView($options, $receptacle_keys, $level_titles, $is_default, $default_keys, $prefix)
420 echo
'<table width="100px">';
423 $receptacle_options = Array();
424 foreach ($options as $key => $value) {
426 if (!in_array(strlen($key), $levels)) {
427 $levels[] = strlen($key);
433 if (in_array($key, $default_keys)) {
434 $receptacle_options[$key] = $key.
'. '.$value;
437 foreach ($receptacle_keys as $receptacle_key) {
438 if ($receptacle_key === $key) {
439 $receptacle_options[$key] = $key.
'. '.$value;
445 $the_options = Array();
446 $count_levels = count($levels);
448 $receptacle_field_name = $prefix;
449 for ($i=0; $i<$count_levels; $i++) {
450 $title = isset($level_titles[$levels[$i]]) ? $level_titles[$levels[$i]] :
'';
452 echo empty($title) ?
'' : $title;
455 foreach ($options as $key => $value) {
456 $field_name = $prefix.
'_stationary_drill_'.$i;
459 if (strlen($key) === $levels[$i]) {
462 $the_options[$key] = $value;
466 $keys = array_keys($the_options);
469 if (isset($keys[0])) {
474 foreach ($options as $search_key => $search_value) {
476 if (strlen($search_key) === $levels[$i-1]) {
477 $found_key = $search_key;
493 $extras = $is_default ?
'disabled="disabled"; onChange="swapOptions_for_'.$prefix.
'(this)";' :
'onChange="swapOptions_for_'.$prefix.
'(this)";';
494 echo combo_box($field_name, $the_options, ($i === $count_levels-1) ? TRUE : FALSE,
'', ($i === $count_levels-1) ? 5 :
'', $extras);
498 $add_on_click =
'addToReceptacle_for_'.$prefix.
'(\''.$field_name.
'\')
';
499 // new column for 'add
' buttons
500 echo '</td><td valign=
"top">
';
501 echo normal_button($prefix.'_drill_down_button
', translate('add
'), $add_on_click);
506 // print the receptacle box
507 echo '<tr><td></td><td>
';
508 $extras = $is_default ? 'disabled=
"disabled"; style=
"width:300px";
' : 'style=
"width:300px";
';
509 echo combo_box($receptacle_field_name, $receptacle_options, TRUE, '', 5, $extras);
511 // print the remove buttons
513 $remove_on_click = 'removeFromReceptacle_for_
'.$prefix.'()
';
514 echo normal_button($prefix.'_drill_down_button
', translate('remove'), $remove_on_click);
515 $remove_all_on_click = 'removeAllFromReceptacle_for_
'.$prefix.'()
';
516 echo normal_button($prefix.'_drill_down_button
', translate('remove_all
'), $remove_all_on_click);
518 // close the receptacle row
522 echo $this->_printJSObjects($options, $prefix);
525 <script type="text/javascript">
526 var prefix_for_<?php echo $prefix ?> = '<?php echo $prefix; ?>
';
527 // select all options in the receptacle box otherwise on commit we will lose our values
528 var receptacleName_for_<?php echo $prefix ?> = '<?php echo $receptacle_field_name; ?>
';
529 var receptacle_for_<?php echo $prefix ?> = document.getElementById(receptacleName_for_<?php echo $prefix ?>);
530 selectAllReceptacleItems_for_<?php echo $prefix ?>(receptacle_for_<?php echo $prefix ?>);
532 function swapOptions_for_<?php echo $prefix ?>(select)
534 // the values to replace with
535 var replaceWith = data_for_<?php echo $prefix ?>[select.value];
537 // get the next box which is the box we will populate
538 var stationaryDrillNum = select.name.match(/.+_stationary_drill_(.+)/);
539 stationaryDrillNum = parseInt(stationaryDrillNum[1]) + 1;
540 var nextBoxName = prefix_for_<?php echo $prefix ?> + '_stationary_drill_
' + stationaryDrillNum;
541 var nextBox = document.getElementById(nextBoxName);
543 // does it exist or are we at the end of the line?
544 if (!isset(nextBox)) {
548 // truncate entries from the next box
549 nextBox.options.length = 0;
551 // populate the next box with the correct entries
553 for (key in replaceWith) {
554 nextBox.options[i] = new Option(replaceWith[key], key);
558 // recurse until there are no more boxes to populate
560 swapOptions_for_<?php echo $prefix ?>(nextBox);
565 function addToReceptacle_for_<?php echo $prefix ?>(selectName_for_<?php echo $prefix ?>)
567 // get the box which holds the values we want to add
568 var select = document.getElementById(selectName_for_<?php echo $prefix ?>);
570 var options = select.options;
571 for (var i=0; i<options.length; i++) {
572 if (options[i].selected) {
574 // we have the selected options, now add them to the receptacle if not currently present
576 for (var j=0; j<receptacle_for_<?php echo $prefix ?>.options.length; j++) {
577 if (receptacle_for_<?php echo $prefix ?>.options[j].value == options[i].value) {
583 // didn't find it, so append it to the receptacle
584 receptacle_for_<?php echo $prefix ?>.options[receptacle_for_<?php echo $prefix ?>.options.length] =
new Option(options[i].value +
'. ' + options[i].text, options[i].value);
589 selectAllReceptacleItems_for_<?php echo $prefix ?>(receptacle_for_<?php echo $prefix ?>);
592 function removeFromReceptacle_for_<?php echo $prefix ?>()
595 var receptacle_for_<?php echo $prefix ?> = document.getElementById(receptacleName_for_<?php echo $prefix ?>);
596 var options = receptacle_for_<?php echo $prefix ?>.options;
597 for (var i=0; i<options.length; i++) {
598 if (options[i].selected) {
599 receptacle_for_<?php echo $prefix ?>.remove(i);
603 selectAllReceptacleItems_for_<?php echo $prefix ?>(receptacle_for_<?php echo $prefix ?>);
606 function removeAllFromReceptacle_for_<?php echo $prefix ?>()
609 var receptacle_for_<?php echo $prefix ?> = document.getElementById(receptacleName_for_<?php echo $prefix ?>);
610 receptacle_for_<?php echo $prefix ?>.options.length = 0;
615 if (typeof v !==
'undefined' && v !== null) {
622 function selectAllReceptacleItems_for_<?php echo $prefix ?>(receptacle_for_<?php echo $prefix ?>)
624 var options = receptacle_for_<?php echo $prefix ?>.options;
625 for (var i=0; i<options.length; i++) {
626 if (!options[i].selected) {
627 options[i].selected =
true;
648 function _printJSObjects($options, $prefix)
650 echo
'<script type="text/javascript">';
651 echo
'var data_for_'.$prefix.
' = {};';
652 foreach ($options as $key => $value) {
653 $children = $this->_getImmediateChildren($options, $key);
655 if (!empty($children)) {
656 echo
'var options_for_'.$prefix.
' = {};';
658 foreach ($children as $child_key => $child_value) {
659 echo
'options_for_'.$prefix.
'[\''.$child_key.
'\'] = \
''.$child_value.
'\';
';
662 data_for_<?php echo $prefix ?>.<?php echo $key; ?> = options_for_<?php echo $prefix ?>;
668 }//end _printJSObjects()
681 function _getImmediateChildren($options, $parent_string, $target_length=NULL)
683 if (is_null($target_length)) {
684 // a child is by definition, 1 char longer
685 $target_length = strlen($parent_string) + 1;
689 foreach ($options as $key => $value) {
690 // ensure we are getting children of this value
691 if ((strlen($key) === $target_length) && (strpos($key, $parent_string) === 0)) {
692 $children[$key] = $value;
696 if (empty($children)) {
697 // look for a deeper level because the hierarchy may not be linear
699 foreach ($options as $key => $value) {
700 if (strlen($key) > $target_length) {
701 if (!in_array(strlen($key), $levels)) {
702 $levels[] = strlen($key);
707 // sort so we are sure the first index is the next level
709 if (isset($levels[0])) {
710 $target_length = $levels[0];
711 // do our search again
712 foreach ($options as $key => $value) {
713 // ensure we are getting children of this value
714 if ((strlen($key) === $target_length) && (strpos($key, $parent_string) === 0)) {
715 $children[$key] = $value;
723 }//end _getImmediateChildren()
736 public function processHierarchy(Metadata_Field_Hierarchy $asset, Backend_Outputter $o, $prefix)
738 // need to have write access to make any changes
739 if (!$asset->writeAccess('attributes
')) return FALSE;
740 $is_contextable = (boolean)$asset->attr('is_contextable
');
742 if ($is_contextable === FALSE) {
743 // If we are not contextable, we might as well be in the default
744 // context... so change to it, and reload our asset
745 $GLOBALS['SQ_SYSTEM
']->changeContext(0);
746 $asset = $GLOBALS['SQ_SYSTEM
']->am->getAsset($asset->id);
749 $GLOBALS['SQ_SYSTEM
']->doTransaction('BEGIN
');
751 $hierarchy_options = Array();
752 if (isset($_POST[$prefix.'_options
'])) {
753 $option_changes = $_POST[$prefix.'_options
'];
754 foreach ($option_changes['key
'] as $i => $key) {
755 if (isset($option_changes['del
'][$i])) continue;
756 $hierarchy_options[trim($key)] = trim($option_changes['val
'][$i]);
760 // now get the new submitted values (if any) and add them to array
761 if (array_key_exists($prefix.'_new_key
', $_POST) === TRUE) {
762 if (strlen(trim($_POST[$prefix.'_new_key
']))>0 && strlen(trim($_POST[$prefix.'_new_val
']))>0) {
763 $new_hierarchy_key = trim($_POST[$prefix.'_new_key
']);
764 $new_hierarchy_val = trim($_POST[$prefix.'_new_val
']);
765 $hierarchy_options[$new_hierarchy_key] = $new_hierarchy_val;
769 // updating asset attribute value
770 $asset->setAttrValue('hierarchy_options
', $hierarchy_options);
772 // saving default value
774 if (!empty($hierarchy_options) && isset($_POST[$prefix.'_default
'])) {
775 $new_default = $_POST[$prefix.'_default
'];
776 if (is_array($new_default)) {
777 $new_default = implode(';
', $new_default);
780 $asset->setAttrValue('default', $new_default);
781 if ($asset->saveAttributes() === TRUE) {
782 $GLOBALS['SQ_SYSTEM
']->doTransaction('COMMIT
');
784 $GLOBALS['SQ_SYSTEM
']->doTransaction('ROLLBACK
');
787 if ($is_contextable === FALSE) {
788 // If we are not contextable, we might as well be in the default
789 // context... so change to it, and reload our asset
790 $GLOBALS['SQ_SYSTEM
']->restoreContext();
791 $asset = $GLOBALS['SQ_SYSTEM
']->am->getAsset($asset->id);
794 // Don't require our own saving of attributes
813 $hierarchy->paintEditParams($prefix.
'_style', $asset->
writeAccess(
'attributes'));
830 if (!$asset->
writeAccess(
'attributes'))
return FALSE;
833 $edit_params = $hierarchy->processEditParams($prefix.
'_style');
834 return $asset->
setAttrValue(
'edit_params', $edit_params);
853 if (is_null($value_str)) {
858 if ($asset->
attr(
'visible_part') ===
'value') {
862 return parent::generateMetadata($asset, $value_str, $tag_value, $keywords);
878 public function _sortHierarchyOptions($hierarchy, $sort_by=0, $show_parents=FALSE, $pad=
'-')
880 if (!is_array($hierarchy))
return NULL;
881 if (empty($hierarchy))
return $hierarchy;
886 $sort_by_key = array_keys($hierarchy);
887 $aok = usort($sort_by_key,
'strcmp');
888 $sort_hier = Array();
889 foreach ($sort_by_key as $key) {
890 $sort_hier[$key] = $hierarchy[$key];
894 $hierarchy = Array();
895 $hierarchy = $sort_hier;
899 $aok = asort($hierarchy);
904 foreach ($hierarchy as $key => $value) {
905 $show_lvl = str_pad(
'', (strlen($key)-1), $pad);
906 $hierarchy[$key] = $show_lvl.$value;
925 public function getHierarchyTree($start_value, $options, $pad=
'; ')
927 $return_value = $start_value;
928 $start_value = strtolower($start_value);
929 $get_values = explode($pad, $start_value);
930 if (is_array($get_values)) {
931 $new_values = Array();
932 foreach ($get_values as $value) {
934 $get_parents = $this->getParentHierarchy($value, $options);
935 if (is_array($get_parents) && !is_null($get_parents)) {
936 foreach ($get_parents as $parent) {
937 if (!in_array($parent, $get_values)) {
938 $new_values[] = $parent;
943 $get_childs = $this->getChildrenHierarchy($value, $options);
944 if (is_array($get_childs) && !is_null($get_childs)) {
945 foreach ($get_childs as $child) {
946 if (!in_array($child, $get_values)) {
947 $new_values[] = $child;
953 foreach ($get_values as $value) {
954 $new_values[] = $value;
958 natsort($new_values);
961 $new_values = array_unique($new_values);
964 $return_value = implode($pad, $new_values);
967 return $return_value;
981 public function getParentHierarchy($value, $options=NULL)
985 if (!empty($value)) {
986 if (is_null($options) || !is_array($options)) {
991 if (strlen($value) == 1)
return $return_val;
993 for ($i=0; $i<strlen($value); $i++) {
995 $parent = substr($value, 0, $i);
996 if (array_key_exists(strtolower($parent), array_change_key_case($options, CASE_LOWER))) {
997 $return_val[] = $parent;
1017 public function getChildrenHierarchy($value, $options=NULL)
1021 if (!empty($value)) {
1022 if (is_null($options) || !is_array($options)) {
1026 foreach ($options as $opt_key => $opt_value) {
1027 if (preg_match(
'/^'.strtolower($value).
'/i', strtolower($opt_key))) {
1028 $return_val[] = strtolower($opt_key);
1046 function isFlatView(&$asset)
1048 $attr = $asset->attr(
'display_type');
1049 return empty($attr) ? TRUE : FALSE;
1062 function isDrillDownView(&$asset)
1064 $attr = $asset->attr(
'display_type');
1065 return empty($attr) ? FALSE : TRUE;
1084 $hierarchy_options = $hierarchy->_params[
'options'];
1086 $level_titles = $asset->
attr(
'level_titles');
1089 foreach ($hierarchy_options as $key => $value) {
1091 if (!in_array(strlen($key), $levels)) {
1092 $levels[] = strlen($key);
1098 foreach ($levels as $id) {
1100 echo
'<td>'.translate(
'level').
' '.$i.
':</td><td>';
1102 echo text_box($prefix.
'_level_titles['.$id.
']', isset($level_titles[$id]) ? htmlspecialchars_decode($level_titles[$id]) :
'').
'</td>';
1104 echo isset($level_titles[$id]) ? $level_titles[$id] :
'';
1130 if (isset($_POST[$prefix.
'_level_titles'])) {
1131 foreach ($_POST[$prefix.
'_level_titles'] as $key => $value) {
1132 $_POST[$prefix.
'_level_titles'][$key] = htmlspecialchars($value);
1134 $asset->
setAttrValue(
'level_titles', $_POST[$prefix.
'_level_titles']);
1156 $display_type = $asset->
attr(
'display_type');
1159 '1' =>
'Drill-Down View',
1162 echo combo_box($prefix.
'_display_type', $options, FALSE, $display_type);
1164 echo $options[$display_type];
1186 if (isset($_POST[$prefix.
'_display_type'])) {
1187 $asset->
setAttrValue(
'display_type', $_POST[$prefix.
'_display_type']);
1188 if ($_POST[$prefix.
'_display_type'] ==
'1') $asset->
setAttrValue(
'multiple', TRUE);