public function parse($ps_expression, $pa_options = null) { $ps_expression = caRemoveAccents($ps_expression); if (!$pa_options) { $pa_options = array(); } $this->init(); if ($this->tokenize($this->preprocess($ps_expression)) == 0) { // nothing to parse return false; } $va_dates = array(); $vn_state = TEP_STATE_BEGIN; $vb_can_accept = false; $vb_circa_is_set = false; while ($va_token = $this->peekToken()) { if ($this->getParseError()) { break; } switch ($vn_state) { # ------------------------------------------------------- case TEP_STATE_BEGIN: switch ($va_token['type']) { # ---------------------- case TEP_TOKEN_INTEGER: // is this a quarter century expression? if ((int) $va_token['value'] > 0 && (int) $va_token['value'] <= 21) { $va_peek = $this->peekToken(2); if ($va_peek['type'] == TEP_TOKEN_ALPHA) { if (preg_match('!^Q([\\d]{1})$!i', $va_peek['value'], $va_matches)) { $vn_q = (int) $va_matches[1]; if ($vn_q >= 1 && $vn_q <= 4) { $vn_start_year = ((int) $va_token['value'] - 1) * 100 + ($vn_q - 1) * 25; $vn_end_year = ((int) $va_token['value'] - 1) * 100 + $vn_q * 25; $va_dates['start'] = array('month' => 1, 'day' => 1, 'year' => $vn_start_year, 'era' => TEP_ERA_AD, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => false, 'dont_window' => true); $va_dates['end'] = array('month' => 12, 'day' => 31, 'year' => $vn_end_year, 'era' => TEP_ERA_AD, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => false, 'dont_window' => true); $this->skipToken(); $this->skipToken(); $vn_state = TEP_STATE_ACCEPT; $vb_can_accept = true; break 2; } } } } // // Look for MYA dates // $va_peek = $this->peekToken(2); if ($va_peek['type'] == TEP_TOKEN_MYA) { $va_dates['start'] = array('month' => 1, 'day' => 1, 'year' => intval($va_token['value']) * -1000000, 'hours' => null, 'minutes' => null, 'seconds' => null, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => false, 'dont_window' => true); $va_dates['end'] = array('month' => 12, 'day' => 31, 'year' => intval($va_token['value']) * -1000000, 'hours' => null, 'minutes' => null, 'seconds' => null, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => false, 'dont_window' => true); $this->skipToken(); $this->skipToken(); $vn_state = TEP_STATE_ACCEPT; $vb_can_accept = true; break 2; } break; # ---------------------- } if ($va_date = $this->_parseDateExpression()) { $va_dates['start'] = $va_date; $vn_state = TEP_STATE_DATE_RANGE_CONJUNCTION; $vb_can_accept = true; break; } else { switch ($va_token['type']) { # ---------------------- case TEP_TOKEN_SEASON_WINTER: case TEP_TOKEN_SEASON_SPRING: case TEP_TOKEN_SEASON_SUMMER: case TEP_TOKEN_SEASON_AUTUMN: $this->skipToken(); $va_peek = $this->peekToken(); if ($va_peek['type'] == TEP_TOKEN_INTEGER) { $vn_start_year = $va_peek['value']; } else { $va_today = $this->gmgetdate(); $vn_start_year = $va_today['year']; } $this->skipToken(); $vn_year_offset = 0; switch ($va_token['type']) { case TEP_TOKEN_SEASON_WINTER: $vn_start_month = 12; $vn_end_month = 3; $vn_year_offset = 1; break; case TEP_TOKEN_SEASON_SPRING: $vn_start_month = 3; $vn_end_month = 6; break; case TEP_TOKEN_SEASON_SUMMER: $vn_start_month = 6; $vn_end_month = 9; break; case TEP_TOKEN_SEASON_AUTUMN: $vn_start_month = 9; $vn_end_month = 12; break; } $va_dates['start'] = array('month' => $vn_start_month, 'day' => 21, 'year' => $vn_start_year, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => false); $va_dates['end'] = array('month' => $vn_end_month, 'day' => 20, 'year' => $vn_start_year + $vn_year_offset, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => false); $vn_state = TEP_STATE_ACCEPT; $vb_can_accept = true; break; # ---------------------- # ---------------------- case TEP_TOKEN_UNDATED: $va_dates['start'] = array('month' => null, 'day' => null, 'year' => null, 'hours' => null, 'minutes' => null, 'seconds' => null, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => 0, 'is_undated' => true); $va_dates['end'] = array('month' => null, 'day' => null, 'year' => null, 'hours' => null, 'minutes' => null, 'seconds' => null, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => 0, 'is_undated' => true); $this->skipToken(); $vn_state = TEP_STATE_ACCEPT; $vb_can_accept = true; break; # ---------------------- # ---------------------- case TEP_TOKEN_ALPHA: # # is this a decade expression? # $va_decade_dates = $this->_parseDecade($va_token, $vb_circa_is_set); if (sizeof($va_decade_dates) > 0) { // found decade $va_next_token = $this->peekToken(); if (is_array($va_next_token) && $va_next_token['type'] == TEP_TOKEN_RANGE_CONJUNCTION) { // decade is part of range $va_dates['start'] = $va_decade_dates['start']; $vn_state = TEP_STATE_DATE_RANGE_END_DATE; $this->skipToken(); // skip range conjunction break; } else { $va_dates = $va_decade_dates; $vn_state = TEP_STATE_ACCEPT; $vb_can_accept = true; break; } } # # is this a century expression? # $this->skipToken(); $va_next_token = $this->getToken(); $vs_next_token_lc = mb_strtolower($va_next_token['value']); $vn_use_romans = $this->opo_datetime_settings->get("useRomanNumeralsForCenturies"); if ($vn_use_romans && in_array($vs_next_token_lc, $this->opo_language_settings->getList("centuryIndicator")) && preg_match("/^([MDCLXVI]+)(.*)\$/", $va_token['value'], $va_roman_matches) || in_array($vs_next_token_lc, $this->opo_language_settings->getList("centuryIndicator")) && preg_match("/^([\\d]+)(.*)\$/", $va_token['value'], $va_matches) || preg_match("/^([\\d]{2})[_]{2}\$/", $va_token['value'], $va_matches)) { $va_ordinals = $this->opo_language_settings->getList("ordinalSuffixes"); $va_ordinals[] = $this->opo_language_settings->get("ordinalSuffixDefault"); //if (in_array($va_matches[2], $va_ordinals)) { if ($vn_use_romans && caIsRomanNumerals($va_roman_matches[1])) { $vn_century = intval(caRomanArabic($va_roman_matches[1])); } else { $vn_century = intval($va_matches[1]); } if (in_array($vs_next_token_lc, $this->opo_language_settings->getList("centuryIndicator"))) { $va_next_token = null; } $vn_is_circa = 0; while ($va_modfier_token = is_array($va_next_token) ? $va_next_token : $this->getToken()) { $va_next_token = null; switch ($va_modfier_token['type']) { case TEP_TOKEN_ERA: if ($va_modfier_token['era'] == TEP_ERA_BC) { $vn_century *= -1; } break; case TEP_TOKEN_QUESTION_MARK_UNCERTAINTY: $vn_is_circa = 1; break; default: $this->setParseError($va_modfier_token, TEP_ERROR_TRAILING_JUNK); break; } } if (preg_match("/^([\\d]{2})[_]{2}\$/", $va_token['value'])) { $vn_century += 1; } if ($vn_century > -100 && $vn_century < 100) { if ($vn_century < 0) { $vn_start_year = $vn_century * 100; $vn_end_year = $vn_century * 100 + 99; } else { $vn_start_year = ($vn_century - 1) * 100; $vn_end_year = ($vn_century - 1) * 100 + 99; } $va_dates['start'] = array('month' => 1, 'day' => 1, 'year' => $vn_start_year, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => $vn_is_circa); $va_dates['end'] = array('month' => 12, 'day' => 31, 'year' => $vn_end_year, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => $vn_is_circa); $vn_state = TEP_STATE_ACCEPT; $vb_can_accept = true; break; } //} } $this->setParseError($va_token, TEP_ERROR_INVALID_EXPRESSION); break; # ---------------------- # ---------------------- case TEP_TOKEN_INTEGER: if ($va_time_element = $this->_parseTimeExpression()) { $va_dates['start'] = $va_time_element; $vn_state = TEP_STATE_TIME_RANGE_CONJUNCTION; $vb_can_accept = true; } else { $this->skipToken(); if ($this->tokens() == 1) { if ($va_token_mya = $this->getToken()) { if ($va_token_mya['type'] == TEP_TOKEN_MYA) { $va_dates['start'] = array('month' => null, 'day' => null, 'year' => intval($va_token['value']) * -1000000, 'hours' => null, 'minutes' => null, 'seconds' => null, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => 0); $va_dates['end'] = array('month' => 12, 'day' => 31, 'year' => intval($va_token['value']) * -1000000, 'hours' => null, 'minutes' => null, 'seconds' => null, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => 0); $vb_can_accept = true; break; } } $vb_can_accept = false; $this->setParseError($va_token, TEP_ERROR_INVALID_EXPRESSION); } } break; # ---------------------- # ---------------------- case TEP_TOKEN_CIRCA: $vb_circa_is_set = true; $this->skipToken(); if ($va_date_element = $this->_parseDateElement()) { if ($va_peek = $this->peekToken()) { if ($va_peek['type'] == TEP_TOKEN_ERA) { $this->skipToken(); if ($va_peek['era'] == TEP_ERA_BC) { $va_date_element['year'] *= -1; } } } $va_dates['start'] = array('month' => $va_date_element['month'], 'day' => $va_date_element['day'], 'year' => $va_date_element['year'], 'hours' => null, 'minutes' => null, 'seconds' => null, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => 1); $va_dates['end'] = array('month' => $va_date_element['month'], 'day' => $va_date_element['day'], 'year' => $va_date_element['year'], 'hours' => null, 'minutes' => null, 'seconds' => null, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => 1); $vn_state = TEP_STATE_DATE_RANGE_CONJUNCTION; $vb_can_accept = true; } break; # ---------------------- # ---------------------- case TEP_TOKEN_TIME: if ($va_time_element = $this->_parseTimeExpression()) { $va_dates['start'] = $va_time_element; $vn_state = TEP_STATE_TIME_RANGE_CONJUNCTION; $vb_can_accept = true; } break; # ---------------------- # ---------------------- case TEP_TOKEN_PRE_RANGE_CONJUNCTION: $this->skipToken(); break; # ---------------------- # ---------------------- case TEP_TOKEN_BEFORE: $this->skipToken(); $vn_state = TEP_STATE_BEFORE_GET_DATE; break; # ---------------------- # ---------------------- case TEP_TOKEN_AFTER: $this->skipToken(); $vn_state = TEP_STATE_AFTER_GET_DATE; break; # ---------------------- # ---------------------- default: $this->setParseError($va_token, TEP_ERROR_INVALID_EXPRESSION); $vb_can_accept = false; break; # ---------------------- } break; # ---------------------- } break; # ------------------------------------------------------- # ------------------------------------------------------- case TEP_STATE_BEFORE_GET_DATE: if ($va_date = $this->_parseDateExpression()) { $va_dates['start'] = array('month' => null, 'day' => null, 'year' => TEP_START_OF_UNIVERSE, 'hours' => null, 'minutes' => null, 'seconds' => null, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => 0); $va_dates['end'] = $va_date; $this->skipToken(); $vn_state = TEP_STATE_ACCEPT; $vb_can_accept = true; } else { $this->setParseError($va_token, TEP_ERROR_INVALID_DATE); $vb_can_accept = false; } break; # ------------------------------------------------------- # ------------------------------------------------------- case TEP_STATE_AFTER_GET_DATE: if ($va_date = $this->_parseDateExpression()) { $va_dates['start'] = $va_date; $va_dates['end'] = array('month' => null, 'day' => null, 'year' => TEP_END_OF_UNIVERSE, 'hours' => null, 'minutes' => null, 'seconds' => null, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => 0); $this->skipToken(); $vn_state = TEP_STATE_ACCEPT; $vb_can_accept = true; } else { $this->setParseError($va_token, TEP_ERROR_INVALID_DATE); $vb_can_accept = false; } break; # ------------------------------------------------------- # ------------------------------------------------------- case TEP_STATE_DATE_RANGE_CONJUNCTION: $vb_circa_is_set = false; if ($va_token['type'] == TEP_TOKEN_RANGE_CONJUNCTION) { $this->skipToken(); if (!$va_dates['start']['day']) { $va_dates['start']['day'] = 1; } if (!$va_dates['start']['month']) { $va_dates['start']['month'] = 1; } $vn_state = TEP_STATE_DATE_RANGE_END_DATE; } else { $this->setParseError($va_token, TEP_ERROR_INVALID_EXPRESSION); } $vb_can_accept = false; break; # ------------------------------------------------------- # ------------------------------------------------------- case TEP_STATE_DATE_RANGE_END_DATE: $vb_circa_is_set = (bool) $va_dates['start']['is_circa']; // carry over circa-ness from start # # is this a decade expression? # $va_decade_dates = $this->_parseDecade($va_token, $vb_circa_is_set); if (sizeof($va_decade_dates) > 0) { // found decade $va_dates['end'] = $va_decade_dates['end']; $vn_state = TEP_STATE_ACCEPT; $vb_can_accept = true; break; } if ($va_date = $this->_parseDateExpression(array('start' => $va_dates['start']))) { $va_dates['end'] = $va_date; if (isset($va_dates['start']['is_circa']) && $va_dates['start']['is_circa']) { $va_dates['end']['is_circa'] = true; } $vn_state = TEP_STATE_ACCEPT; $vb_can_accept = true; } else { $this->setParseError($va_token, TEP_ERROR_INVALID_EXPRESSION); $vb_can_accept = false; } break; # ------------------------------------------------------- # ------------------------------------------------------- case TEP_STATE_TIME_RANGE_CONJUNCTION: if ($va_token['type'] == TEP_TOKEN_RANGE_CONJUNCTION) { $this->skipToken(); $vn_state = TEP_STATE_TIME_RANGE_END_TIME; } else { $this->setParseError($va_token, TEP_ERROR_INVALID_EXPRESSION); } $vb_can_accept = false; break; # ------------------------------------------------------- # ------------------------------------------------------- case TEP_STATE_TIME_RANGE_END_TIME: if ($va_time = $this->_parseTimeExpression()) { $va_dates['end'] = $va_time; $vn_state = TEP_STATE_ACCEPT; $vb_can_accept = true; } else { $this->setParseError($va_token, TEP_ERROR_INVALID_TIME); $vb_can_accept = false; } break; # ------------------------------------------------------- # ------------------------------------------------------- case TEP_STATE_ACCEPT: $this->setParseError($va_token, TEP_ERROR_TRAILING_JUNK); $vb_can_accept = true; break; } # ------------------------------------------------------- } if ($this->getParseError()) { return false; } else { if (!$vb_can_accept) { if ($vn_state == TEP_STATE_DATE_RANGE_END_DATE) { // Allow omission of end date of range to be taken as present/ongoing date // This lets a user enter dates like "1971 - " instead of "after 1971" $va_dates['end'] = array('month' => null, 'day' => null, 'year' => TEP_END_OF_UNIVERSE, 'hours' => null, 'minutes' => null, 'seconds' => null, 'uncertainty' => 0, 'uncertainty_units' => '', 'is_circa' => 0); return $this->_processParseResults($va_dates, $pa_options); } $this->setParseError(null, TEP_ERROR_TRAILING_JUNK); return false; } else { return $this->_processParseResults($va_dates, $pa_options); } } }
/** * * */ protected function GetHierarchyLevelData($pa_ids) { $vo_dm = Datamodel::load(); $o_config = Configuration::load(); $t_object = new ca_objects(); $va_level_data = array(); foreach ($pa_ids as $pn_id) { $va_params = $this->getItemIDComponents($pn_id); $vs_table = $va_params['table']; $vn_id = $va_params['id']; $vn_start = $va_params['start']; $vn_item_count = 0; $t_item = $vo_dm->getInstanceByTableName($vs_table, true); $vs_label_table_name = $t_item->getLabelTableName(); $vs_label_display_field_name = $t_item->getLabelDisplayField(); $vs_pk = $t_item->primaryKey(); if ($vn_start < 0) { $vn_start = 0; } $va_items_for_locale = array(); if (!$vn_id && method_exists($t_item, "getHierarchyList")) { $vn_id = $this->request->getParameter('root_item_id', pString); $va_params = $this->getItemIDComponents($vn_id); $vs_table = $va_params['table']; $vn_id = $va_params['id']; $vn_start = $va_params['start']; $t_item = $vo_dm->getInstanceByTableName($vs_table, true); $vs_label_table_name = $t_item->getLabelTableName(); $vs_label_display_field_name = $t_item->getLabelDisplayField(); $vs_pk = $t_item->primaryKey(); $t_item->load($vn_id); $va_tmp = array($vs_pk => $vn_id = $t_item->get($vs_table . '.' . $vs_pk), 'item_id' => $vs_table . '-' . $vn_id, 'parent_id' => $t_item->get($vs_table . '.parent_id'), 'idno' => $t_item->get($vs_table . '.idno'), $vs_label_display_field_name => $t_item->get($vs_table . '.preferred_labels.' . $vs_label_display_field_name), 'locale_id' => $t_item->get($vs_table . '.' . 'locale_id')); if (!$va_tmp[$vs_label_display_field_name]) { $va_tmp[$vs_label_display_field_name] = $va_tmp['idno']; } if (!$va_tmp[$vs_label_display_field_name]) { $va_tmp[$vs_label_display_field_name] = '???'; } if (!($vs_item_template = trim($o_config->get("{$vs_table}_hierarchy_browser_display_settings")))) { $vs_item_template = "^{$vs_table}.preferred_labels.{$vs_label_display_field_name}"; } $va_tmp['name'] = caProcessTemplateForIDs($vs_item_template, $vs_table, array($va_tmp[$vs_pk])); // Child count is only valid if has_children is not null $va_tmp['children'] = $t_item->get('has_children') ? (int) $t_item->get('child_count') : 1; // TODO: fix $va_items[$va_tmp[$vs_pk]][$va_tmp['locale_id']] = $va_tmp; $va_items_for_locale = caExtractValuesByUserLocale($va_items); } else { if ($t_item->load($vn_id)) { // id is the id of the parent for the level we're going to return $va_additional_wheres = array(); $t_label_instance = $t_item->getLabelTableInstance(); if ($t_label_instance && $t_label_instance->hasField('is_preferred')) { $va_additional_wheres[] = "(({$vs_label_table_name}.is_preferred = 1) OR ({$vs_label_table_name}.is_preferred IS NULL))"; } if (!is_array($va_sorts = $o_config->getList($vs_table . '_hierarchy_browser_sort_values')) || !sizeof($va_sorts)) { $va_sorts = null; } foreach ($va_sorts as $vn_i => $vs_sort_fld) { $va_tmp = explode(".", $vs_sort_fld); if ($va_tmp[1] == 'preferred_labels') { $va_tmp[0] = $vs_label_table_name; if (!($va_tmp[1] = $va_tmp[2])) { $va_tmp[1] = $vs_label_display_field_name; } unset($va_tmp[2]); $va_sorts[$vn_i] = join(".", $va_tmp); } } if (!in_array($vs_sort_dir = strtolower($o_config->get($vs_table . '_hierarchy_browser_sort_direction')), array('asc', 'desc'))) { $vs_sort_dir = 'asc'; } $qr_children = $t_item->getHierarchyChildrenAsQuery($t_item->getPrimaryKey(), array('additionalTableToJoin' => $vs_label_table_name, 'additionalTableJoinType' => 'LEFT', 'additionalTableSelectFields' => array($vs_label_display_field_name, 'locale_id'), 'additionalTableWheres' => $va_additional_wheres, 'returnChildCounts' => true, 'sort' => $va_sorts, 'sortDirection' => $vs_sort_dir)); $va_items = array(); if (!($vs_item_template = trim($o_config->get("{$vs_table}_hierarchy_browser_display_settings")))) { $vs_item_template = "^{$vs_table}.preferred_labels.{$vs_label_display_field_name}"; } $va_child_counts = array(); if (($vn_max_items_per_page = $this->request->getParameter('max', pInteger)) < 1 || $vn_max_items_per_page > 1000) { $vn_max_items_per_page = null; } $vn_c = 0; $vn_item_count = $qr_children->numRows(); $qr_children->seek($vn_start); while ($qr_children->nextRow()) { $va_tmp = array($vs_pk => $vn_id = $qr_children->get($vs_table . '.' . $vs_pk), 'item_id' => $vs_table . '-' . $vn_id, 'parent_id' => $qr_children->get($vs_table . '.parent_id'), 'idno' => $qr_children->get($vs_table . '.idno'), 'locale_id' => $qr_children->get($vs_table . '.' . 'locale_id')); if (!$va_tmp[$vs_label_display_field_name]) { $va_tmp[$vs_label_display_field_name] = $va_tmp['idno']; } if (!$va_tmp[$vs_label_display_field_name]) { $va_tmp[$vs_label_display_field_name] = '???'; } $va_tmp['name'] = caProcessTemplateForIDs($vs_item_template, $vs_table, array($va_tmp[$vs_pk])); // Child count is only valid if has_children is not null $va_tmp['children'] = $qr_children->get('has_children') ? (int) $qr_children->get('child_count') : 0; if (is_array($va_sorts)) { $vs_sort_acc = array(); foreach ($va_sorts as $vs_sort) { $vs_sort_acc[] = $qr_children->get($vs_sort); } $va_tmp['sort'] = join(";", $vs_sort_acc); } $va_items[$va_tmp['item_id']][$va_tmp['locale_id']] = $va_tmp; $vn_c++; if (!is_null($vn_max_items_per_page) && $vn_c >= $vn_max_items_per_page) { break; } } if ($t_item->tableName() == 'ca_collections') { $vs_object_collection_rel_type = $o_config->get('ca_objects_x_collections_hierarchy_relationship_type'); $va_cross_table_items = $t_item->getRelatedItems('ca_objects', array('restrictToRelationshipTypes' => array($vs_object_collection_rel_type))); $vn_item_count += sizeof($va_cross_table_items); $va_ids = array(); foreach ($va_cross_table_items as $vn_x_item_id => $va_x_item) { $va_items['ca_objects-' . $vn_x_item_id][$va_x_item['locale_id']] = $va_x_item; $va_items['ca_objects-' . $va_x_item['object_id']][$va_x_item['locale_id']]['item_id'] = 'ca_objects-' . $va_x_item['object_id']; $va_items['ca_objects-' . $va_x_item['object_id']][$va_x_item['locale_id']]['parent_id'] = $vn_id; unset($va_items['ca_objects-' . $vn_x_item_id][$va_x_item['locale_id']]['labels']); $va_items['ca_objects-' . $va_x_item['object_id']][$va_x_item['locale_id']]['children'] = 0; $va_ids[] = $va_x_item['object_id']; } if (!($vs_item_template = trim($o_config->get("ca_objects_hierarchy_browser_display_settings")))) { $vs_item_template = "^ca_objects.preferred_labels.name"; } if (sizeof($va_ids)) { $va_child_counts = $t_object->getHierarchyChildCountsForIDs($va_ids); $va_templates = caProcessTemplateForIDs($vs_item_template, 'ca_objects', $va_ids, array('returnAsArray' => true)); foreach ($va_child_counts as $vn_id => $vn_c) { $va_items['ca_objects-' . $vn_id][$va_x_item['locale_id']]['children'] = $vn_c; } foreach ($va_ids as $vn_i => $vn_id) { $va_items['ca_objects-' . $vn_id][$va_x_item['locale_id']]['name'] = $va_templates[$vn_i]; } } } $va_items_for_locale = caExtractValuesByUserLocale($va_items); $vs_rank_fld = $t_item->getProperty('RANK'); $va_sorted_items = array(); foreach ($va_items_for_locale as $vn_id => $va_node) { $vs_key = caSortableValue(mb_strtolower(preg_replace('![^A-Za-z0-9]!', '_', caRemoveAccents($va_node['name'])))) . "_" . $vn_id; if (isset($va_node['sort']) && $va_node['sort']) { $va_sorted_items[$va_node['sort']][$vs_key] = $va_node; } else { if ($vs_rank_fld && ($vs_rank = (int) sprintf("%08d", $va_node[$vs_rank_fld]))) { $va_sorted_items[$vs_rank][$vs_key] = $va_node; } else { $va_sorted_items[$vs_key][$vs_key] = $va_node; } } } ksort($va_sorted_items); if ($vs_sort_dir == 'desc') { $va_sorted_items = array_reverse($va_sorted_items); } $va_items_for_locale = array(); foreach ($va_sorted_items as $vs_k => $va_v) { ksort($va_v); if ($vs_sort_dir == 'desc') { $va_v = array_reverse($va_v); } $va_items_for_locale = array_merge($va_items_for_locale, $va_v); } } } $va_items_for_locale['_sortOrder'] = array_keys($va_items_for_locale); $va_items_for_locale['_primaryKey'] = $t_item->primaryKey(); // pass the name of the primary key so the hierbrowser knows where to look for item_id's $va_items_for_locale['_itemCount'] = $vn_item_count; //$qr_children ? $qr_children->numRows() : 0; $va_level_data[$pn_id] = $va_items_for_locale; } return $va_level_data; }
/** * Takes a word and returns it reduced to its stem. * * Non-alphanumerics and hyphens are removed, except for dots and * apostrophes, and if the word is less than three characters in * length, it will be stemmed according to the five-step * Porter stemming algorithm. * * Note special cases here: hyphenated words (such as half-life) will * only have the base after the last hyphen stemmed (so half-life would * only have "life" subject to stemming). Handles multi-hyphenated * words, too. * * @param string $word Word to reduce * @access public * @return string Stemmed word */ public function stem($word, $lang = 'en') { if (empty($word)) { return false; } $orig_word = $word; if (isset($this->opa_stem_cache[$word])) { return $this->opa_stem_cache[$word]; } // Use PECL function if it is installed if (function_exists('stem')) { $this->opa_stem_cache[$word] = stem($word, $this->lang2code($lang)); return $this->opa_stem_cache[$word]; } $result = ''; $word = strtolower(caRemoveAccents($word)); // Strip punctuation, etc. Keep ' and . for URLs and contractions. if (substr($word, -2) == "'s") { $word = substr($word, 0, -2); } if (function_exists('iconv')) { $word = iconv('UTF-8', 'ASCII//TRANSLIT//IGNORE', $word); } $word = preg_replace("/[^a-z0-9'.-]/", '', $word); $first = ''; if (strpos($word, '-') !== false) { //list($first, $word) = explode('-', $word); //$first .= '-'; $first = substr($word, 0, strrpos($word, '-') + 1); // Grabs hyphen too $word = substr($word, strrpos($word, '-') + 1); } if (strlen($word) > 2) { $word = $this->_step_1($word); $word = $this->_step_2($word); $word = $this->_step_3($word); $word = $this->_step_4($word); $word = $this->_step_5($word); } $result = $first . $word; $this->opa_stem_cache[$orig_word] = $result; return $result; }
/** * Given a item_id (request parameter 'id') returns a list of direct children for use in the hierarchy browser * Returned data is JSON format */ public function GetHierarchyLevel() { header("Content-type: application/json"); $ps_bundle = (string) $this->request->getParameter('bundle', pString); $pa_ids = explode(";", $ps_ids = $this->request->getParameter('id', pString)); if (!sizeof($pa_ids)) { $pa_ids = array(null); } $t_item = $this->opo_item_instance; if (!$t_item->isHierarchical()) { return; } $va_level_data = array(); foreach ($pa_ids as $pn_id) { $va_tmp = explode(":", $pn_id); $vn_id = $va_tmp[0]; $vn_start = (int) $va_tmp[1]; if ($vn_start < 0) { $vn_start = 0; } if (sizeof($va_tmp) < 2) { $pn_id = '0:0'; } $va_items_for_locale = array(); $vb_gen = true; if (!$vn_id && method_exists($t_item, "getHierarchyList")) { $vn_id = (int) $this->request->getParameter('root_item_id', pInteger); $t_item->load($vn_id); // no id so by default return list of available hierarchies $va_items_for_locale = $t_item->getHierarchyList(); if (sizeof($va_items_for_locale) == 1 && $this->request->getAppConfig()->get($t_item->tableName() . '_hierarchy_browser_hide_root')) { $va_item = array_shift($va_items_for_locale); $vn_id = $va_item['item_id']; } else { $vb_gen = false; } } if ($vb_gen && $t_item->load($vn_id)) { // id is the id of the parent for the level we're going to return $vs_table_name = $t_item->tableName(); $vs_label_table_name = $this->opo_item_instance->getLabelTableName(); $vs_label_display_field_name = $this->opo_item_instance->getLabelDisplayField(); $vs_pk = $this->opo_item_instance->primaryKey(); $va_additional_wheres = array(); $t_label_instance = $this->opo_item_instance->getLabelTableInstance(); if ($t_label_instance && $t_label_instance->hasField('is_preferred')) { $va_additional_wheres[] = "(({$vs_label_table_name}.is_preferred = 1) OR ({$vs_label_table_name}.is_preferred IS NULL))"; } $o_config = Configuration::load(); if (!is_array($va_sorts = $o_config->getList($this->ops_table_name . '_hierarchy_browser_sort_values')) || !sizeof($va_sorts)) { $va_sorts = array(); } foreach ($va_sorts as $vn_i => $vs_sort_fld) { $va_tmp = explode(".", $vs_sort_fld); if ($va_tmp[1] == 'preferred_labels') { $va_tmp[0] = $vs_label_table_name; if (!($va_tmp[1] = $va_tmp[2])) { $va_tmp[1] = $vs_label_display_field_name; } unset($va_tmp[2]); $va_sorts[$vn_i] = join(".", $va_tmp); } } if (!in_array($vs_sort_dir = strtolower($o_config->get($this->ops_table_name . '_hierarchy_browser_sort_direction')), array('asc', 'desc'))) { $vs_sort_dir = 'asc'; } $va_items = array(); if (is_array($va_item_ids = $t_item->getHierarchyChildren($t_item->getPrimaryKey(), array('idsOnly' => true))) && sizeof($va_item_ids)) { $qr_children = $t_item->makeSearchResult($t_item->tableName(), $va_item_ids); $va_child_counts = $t_item->getHierarchyChildCountsForIDs($va_item_ids); if (!($vs_item_template = trim($o_config->get("{$vs_table_name}_hierarchy_browser_display_settings")))) { $vs_item_template = "^{$vs_table_name}.preferred_labels.{$vs_label_display_field_name}"; } if (($vn_max_items_per_page = $this->request->getParameter('max', pInteger)) < 1 || $vn_max_items_per_page > 1000) { $vn_max_items_per_page = 100; } $vn_c = 0; while ($qr_children->nextHit()) { $va_tmp = array($vs_pk => $vn_id = $qr_children->get($this->ops_table_name . '.' . $vs_pk), 'item_id' => $vn_id, 'parent_id' => $qr_children->get($this->ops_table_name . '.parent_id'), 'idno' => $qr_children->get($this->ops_table_name . '.idno'), $vs_label_display_field_name => $qr_children->get($this->ops_table_name . '.preferred_labels.' . $vs_label_display_field_name), 'locale_id' => $qr_children->get($this->ops_table_name . '.' . 'locale_id')); if (!$va_tmp[$vs_label_display_field_name]) { $va_tmp[$vs_label_display_field_name] = $va_tmp['idno']; } if (!$va_tmp[$vs_label_display_field_name]) { $va_tmp[$vs_label_display_field_name] = '???'; } $va_tmp['name'] = caProcessTemplateForIDs($vs_item_template, $vs_table_name, array($va_tmp[$vs_pk]), array('requireLinkTags' => true)); if (!$va_tmp['name']) { $va_tmp['name'] = '??? ' . $va_tmp[$vs_pk]; } // Child count is only valid if has_children is not null $va_tmp['children'] = isset($va_child_counts[$vn_id]) ? (int) $va_child_counts[$vn_id] : 0; if (strlen($vs_enabled = $qr_children->get('is_enabled')) > 0) { $va_tmp['is_enabled'] = $vs_enabled; } if (is_array($va_sorts)) { $vs_sort_acc = array(); foreach ($va_sorts as $vs_sort) { $vs_sort_acc[] = $qr_children->get($vs_sort, array('sortable' => true)); } $va_tmp['sort'] = join(";", $vs_sort_acc); } $va_items[$va_tmp[$vs_pk]][$va_tmp['locale_id']] = $va_tmp; $vn_c++; } $va_items_for_locale = caExtractValuesByUserLocale($va_items); } $vs_rank_fld = $t_item->getProperty('RANK'); $va_sorted_items = array(); foreach ($va_items_for_locale as $vn_id => $va_node) { $vs_key = caSortableValue(mb_strtolower(preg_replace('![^A-Za-z0-9]!', '_', caRemoveAccents($va_node['name'])))) . "_" . $vn_id; if (isset($va_node['sort']) && $va_node['sort']) { $va_sorted_items[$va_node['sort']][$vs_key] = $va_node; } else { if ($vs_rank_fld && ($vs_rank = (int) sprintf("%08d", $va_node[$vs_rank_fld]))) { $va_sorted_items[$vs_rank][$vs_key] = $va_node; } else { $va_sorted_items[$vs_key][$vs_key] = $va_node; } } } ksort($va_sorted_items); if ($vs_sort_dir == 'desc') { $va_sorted_items = array_reverse($va_sorted_items); } $va_items_for_locale = array(); $va_sorted_items = array_slice($va_sorted_items, $vn_start, $vn_max_items_per_page); foreach ($va_sorted_items as $vs_k => $va_v) { ksort($va_v); if ($vs_sort_dir == 'desc') { $va_v = array_reverse($va_v); } $va_items_for_locale = array_merge($va_items_for_locale, $va_v); } } $va_items_for_locale['_sortOrder'] = array_keys($va_items_for_locale); $va_items_for_locale['_primaryKey'] = $t_item->primaryKey(); // pass the name of the primary key so the hierbrowser knows where to look for item_id's $va_items_for_locale['_itemCount'] = $qr_children ? $qr_children->numHits() : 0; $va_level_data[$pn_id] = $va_items_for_locale; } if (!$this->request->getParameter('init', pInteger)) { // only set remember "last viewed" if the load is done interactively // if the GetHierarchyLevel() call is part of the initialization of the hierarchy browser // then all levels are loaded, sometimes out-of-order; if we record these initialization loads // as the 'last viewed' we can end up losing the true 'last viewed' value // // ... so the hierbrowser passes an extra 'init' parameters set to 1 if the GetHierarchyLevel() call // is part of a browser initialization $this->request->session->setVar($this->ops_table_name . '_' . $ps_bundle . '_browse_last_id', array_pop($pa_ids)); } $this->view->setVar(str_replace(' ', '_', $this->ops_name_singular) . '_list', $va_level_data); return $this->render(str_replace(' ', '_', $this->ops_name_singular) . '_hierarchy_level_json.php'); }
/** * */ public function __call($ps_function, $pa_args) { $o_config = caGetBrowseConfig(); $this->view->setVar("config", $o_config); $ps_function = strtolower($ps_function); $ps_type = $this->request->getActionExtra(); if (!($va_browse_info = caGetInfoForBrowseType($ps_function))) { // invalid browse type – throw error die("Invalid browse type"); } MetaTagManager::setWindowTitle($this->request->config->get("app_display_name") . ": " . _t("Browse %1", $va_browse_info["displayName"])); $this->view->setVar("browse_type", $ps_function); $vs_class = $va_browse_info['table']; $va_types = caGetOption('restrictToTypes', $va_browse_info, array(), array('castTo' => 'array')); $this->opo_result_context = new ResultContext($this->request, $va_browse_info['table'], $this->ops_find_type); // Don't set last find when loading facet, as some other controllers use this action and setting // last find will disrupt ResultContext navigation by setting it to "browse" when in fact a search (or some other // context) is still in effect. if (!$this->request->getParameter('getFacet', pInteger)) { $this->opo_result_context->setAsLastFind(); } $this->view->setVar('browseInfo', $va_browse_info); $this->view->setVar('paging', in_array(strtolower($va_browse_info['paging']), array('continous', 'nextprevious', 'letter')) ? strtolower($va_browse_info['paging']) : 'continous'); $this->view->setVar('name', $va_browse_info['displayName']); $this->view->setVar('options', caGetOption('options', $va_browse_info, array(), array('castTo' => 'array'))); $ps_view = $this->request->getParameter('view', pString); $va_views = caGetOption('views', $va_browse_info, array(), array('castTo' => 'array')); if (!is_array($va_views) || sizeof($va_views) == 0) { $va_views = array('list' => array(), 'images' => array(), 'timeline' => array(), 'map' => array(), 'timelineData' => array(), 'pdf' => array()); } else { $va_views['pdf'] = array(); $va_views['timelineData'] = array(); } if (!in_array($ps_view, array_keys($va_views))) { $ps_view = array_shift(array_keys($va_views)); } $vs_format = $ps_view == 'timelineData' ? 'json' : 'html'; caAddPageCSSClasses(array($vs_class, $ps_function)); $this->view->setVar('isNav', $vb_is_nav = (bool) $this->request->getParameter('isNav', pInteger)); // flag for browses that originate from nav bar $t_instance = $this->getAppDatamodel()->getInstanceByTableName($vs_class, true); $vn_type_id = $t_instance->getTypeIDForCode($ps_type); $this->view->setVar('t_instance', $t_instance); $this->view->setVar('table', $va_browse_info['table']); $this->view->setVar('primaryKey', $t_instance->primaryKey()); $this->view->setVar('browse', $o_browse = caGetBrowseInstance($vs_class)); $this->view->setVar('views', caGetOption('views', $va_browse_info, array(), array('castTo' => 'array'))); $this->view->setVar('view', $ps_view); $this->view->setVar('viewIcons', $o_config->getAssoc("views")); // // Load existing browse if key is specified // if ($ps_cache_key = $this->request->getParameter('key', pString)) { $o_browse->reload($ps_cache_key); } if (is_array($va_types) && sizeof($va_types)) { $o_browse->setTypeRestrictions($va_types, array('dontExpandHierarchically' => caGetOption('dontExpandTypesHierarchically', $va_browse_info, false))); } // // Clear criteria if required // if ($vs_remove_criterion = $this->request->getParameter('removeCriterion', pString)) { $o_browse->removeCriteria($vs_remove_criterion, array($this->request->getParameter('removeID', pString))); } if ((bool) $this->request->getParameter('clear', pInteger)) { $o_browse->removeAllCriteria(); } // // Return facet content // if ($this->request->getParameter('getFacet', pInteger)) { $vs_facet = $this->request->getParameter('facet', pString); $vn_s = $vb_is_nav ? $this->request->getParameter('s', pInteger) : 0; // start menu-based browse menu facet data at page boundary; all others get the full facet $this->view->setVar('start', $vn_s); $this->view->setVar('limit', $vn_limit = $vb_is_nav ? 500 : null); // break facet into pages for menu-based browse menu $this->view->setVar('facet_name', $vs_facet); $this->view->setVar('key', $o_browse->getBrowseID()); $this->view->setVar('facet_info', $va_facet_info = $o_browse->getInfoForFacet($vs_facet)); # --- pull in different views based on format for facet - alphabetical, list, hierarchy switch ($va_facet_info["group_mode"]) { case "alphabetical": case "list": default: $this->view->setVar('facet_content', $o_browse->getFacet($vs_facet, array("checkAccess" => $this->opa_access_values, 'start' => $vn_s, 'limit' => $vn_limit))); $this->render("Browse/list_facet_html.php"); break; case "hierarchical": $this->render("Browse/hierarchy_facet_html.php"); break; } return; } // // Add criteria and execute // // Get any preset-criteria $va_base_criteria = caGetOption('baseCriteria', $va_browse_info, null); if ($vs_facet = $this->request->getParameter('facet', pString)) { $o_browse->addCriteria($vs_facet, array($this->request->getParameter('id', pString))); } else { if ($o_browse->numCriteria() == 0) { if (is_array($va_base_criteria)) { foreach ($va_base_criteria as $vs_facet => $vs_value) { $o_browse->addCriteria($vs_facet, $vs_value); } } else { $o_browse->addCriteria("_search", array("*")); } } } // // Sorting // $vb_sort_changed = false; if (!($ps_sort = $this->request->getParameter("sort", pString))) { if (!($ps_sort = $this->opo_result_context->getCurrentSort())) { if (is_array($va_sorts = caGetOption('sortBy', $va_browse_info, null))) { $ps_sort = array_shift(array_keys($va_sorts)); $vb_sort_changed = true; } } } else { $vb_sort_changed = true; } if ($vb_sort_changed) { # --- set the default sortDirection if available $va_sort_direction = caGetOption('sortDirection', $va_browse_info, null); if ($ps_sort_direction = $va_sort_direction[$ps_sort]) { $this->opo_result_context->setCurrentSortDirection($ps_sort_direction); } } if (!($ps_sort_direction = $this->request->getParameter("direction", pString))) { if (!($ps_sort_direction = $this->opo_result_context->getCurrentSortDirection())) { $ps_sort_direction = 'asc'; } } $this->opo_result_context->setCurrentSort($ps_sort); $this->opo_result_context->setCurrentSortDirection($ps_sort_direction); $va_sort_by = caGetOption('sortBy', $va_browse_info, null); $this->view->setVar('sortBy', is_array($va_sort_by) ? $va_sort_by : null); $this->view->setVar('sortBySelect', $vs_sort_by_select = is_array($va_sort_by) ? caHTMLSelect("sort", $va_sort_by, array('id' => "sort"), array("value" => $ps_sort)) : ''); $this->view->setVar('sortControl', $vs_sort_by_select ? _t('Sort with %1', $vs_sort_by_select) : ''); $this->view->setVar('sort', $ps_sort); $this->view->setVar('sort_direction', $ps_sort_direction); if (caGetOption('dontShowChildren', $va_browse_info, false)) { $o_browse->addResultFilter('ca_objects.parent_id', 'is', 'null'); } // // Current criteria // $va_criteria = $o_browse->getCriteriaWithLabels(); if (isset($va_criteria['_search']) && isset($va_criteria['_search']['*'])) { unset($va_criteria['_search']); } $o_browse->execute(array('checkAccess' => $this->opa_access_values, 'showAllForNoCriteriaBrowse' => true)); // // Facets // if ($vs_facet_group = caGetOption('facetGroup', $va_browse_info, null)) { $o_browse->setFacetGroup($vs_facet_group); } $va_available_facet_list = caGetOption('availableFacets', $va_browse_info, null); $va_facets = $o_browse->getInfoForAvailableFacets(); foreach ($va_facets as $vs_facet_name => $va_facet_info) { if (isset($va_base_criteria[$vs_facet_name])) { continue; } // skip base criteria $va_facets[$vs_facet_name]['content'] = $o_browse->getFacet($vs_facet_name, array("checkAccess" => $this->opa_access_values, 'checkAvailabilityOnly' => caGetOption('deferred_load', $va_facet_info, false, array('castTo' => 'bool')))); } $this->view->setVar('facets', $va_facets); $this->view->setVar('key', $vs_key = $o_browse->getBrowseID()); $this->request->session->setVar($ps_function . '_last_browse_id', $vs_key); // remove base criteria from display list if (is_array($va_base_criteria)) { foreach ($va_base_criteria as $vs_base_facet => $vs_criteria_value) { unset($va_criteria[$vs_base_facet]); } } $va_criteria_for_display = array(); foreach ($va_criteria as $vs_facet_name => $va_criterion) { $va_facet_info = $o_browse->getInfoForFacet($vs_facet_name); foreach ($va_criterion as $vn_criterion_id => $vs_criterion) { $va_criteria_for_display[] = array('facet' => $va_facet_info['label_singular'], 'facet_name' => $vs_facet_name, 'value' => $vs_criterion, 'id' => $vn_criterion_id); } } $this->view->setVar('criteria', $va_criteria_for_display); // // Results // $qr_res = $o_browse->getResults(array('sort' => $va_sort_by[$ps_sort], 'sort_direction' => $ps_sort_direction)); if ($vs_letter_bar_field = caGetOption('showLetterBarFrom', $va_browse_info, null)) { // generate letter bar $va_letters = array(); while ($qr_res->nextHit()) { $va_letters[caRemoveAccents(mb_strtolower(mb_substr($qr_res->get($vs_letter_bar_field), 0, 1)))]++; } $this->view->setVar('letterBar', $va_letters); $qr_res->seek(0); } $this->view->setVar('showLetterBar', (bool) $vs_letter_bar_field); if ($vs_letter_bar_field && ($vs_l = mb_strtolower($this->request->getParameter('l', pString)))) { $va_filtered_ids = array(); while ($qr_res->nextHit()) { if (caRemoveAccents(mb_strtolower(mb_substr($qr_res->get($vs_letter_bar_field), 0, 1))) == $vs_l) { $va_filtered_ids[] = $qr_res->getPrimaryKey(); } } if (sizeof($va_filtered_ids) > 0) { $qr_res = caMakeSearchResult($vs_class, $va_filtered_ids); } } $this->view->setVar('letter', $vs_l); $this->view->setVar('result', $qr_res); if (!($pn_hits_per_block = $this->request->getParameter("n", pString))) { if (!($pn_hits_per_block = $this->opo_result_context->getItemsPerPage())) { $pn_hits_per_block = $o_config->get("defaultHitsPerBlock"); } } $this->opo_result_context->getItemsPerPage($pn_hits_per_block); $this->view->setVar('hits_per_block', $pn_hits_per_block); $this->view->setVar('start', $vn_start = $this->request->getParameter('s', pInteger)); $this->opo_result_context->setParameter('key', $vs_key); if (!$this->request->isAjax()) { if (($vn_key_start = $vn_start - 500) < 0) { $vn_key_start = 0; } $qr_res->seek($vn_key_start); $this->opo_result_context->setResultList($qr_res->getPrimaryKeyValues(500)); $qr_res->seek($vn_start); } $this->opo_result_context->saveContext(); if ($ps_type) { if ($this->render("Browse/{$vs_class}_{$ps_type}_{$ps_view}_{$vs_format}.php")) { return; } } switch ($ps_view) { case 'pdf': $this->_genExport($qr_res, $this->request->getParameter("export_format", pString), $vs_search_expression, $this->getCriteriaForDisplay($o_browse)); break; case 'timelineData': $this->view->setVar('view', 'timeline'); $this->render("Browse/browse_results_timelineData_json.php"); break; default: $this->opo_result_context->setCurrentView($ps_view); $this->render("Browse/browse_results_html.php"); break; } }
/** * Given a item_id (request parameter 'id') returns a list of direct children for use in the hierarchy browser * Returned data is JSON format */ public function GetHierarchyLevel() { $ps_bundle = (string) $this->request->getParameter('bundle', pString); $pa_ids = explode(";", $ps_ids = $this->request->getParameter('id', pString)); if (!sizeof($pa_ids)) { $pa_ids = array(null); } $t_item = $this->opo_item_instance; $vs_template = $t_item->getAppConfig()->get('ca_list_items_hierarchy_browser_display_settings'); $va_lists = array(); if ($ps_lists = $this->request->getParameter('lists', pString)) { $va_lists = explode(";", $ps_lists); } if (($vn_max_items_per_page = $this->request->getParameter('max', pInteger)) < 1 || $vn_max_items_per_page > 1000) { $vn_max_items_per_page = 100; } $va_level_data = array(); foreach ($pa_ids as $pn_id) { $va_tmp = explode(":", $pn_id); $vn_id = $va_tmp[0]; $vn_start = (int) $va_tmp[1]; if ($vn_start < 0) { $vn_start = 0; } if (!$vn_id && method_exists($t_item, "getHierarchyList")) { if (!($pn_list_id = $this->request->getParameter('list_id', pInteger))) { // no id so by default return list of available hierarchies $va_list_items = $t_item->getHierarchyList(); if (sizeof($va_lists)) { // filter out lists that weren't specified foreach ($va_list_items as $vn_list_id => $va_list) { if (!in_array($vn_list_id, $va_lists) && !in_array($va_list['list_code'], $va_lists)) { unset($va_list_items[$vn_list_id]); } } } else { if ($this->request->getParameter('voc', pInteger)) { // Only show vocabularies foreach ($va_list_items as $vn_list_id => $va_list) { if (!$va_list['use_as_vocabulary']) { unset($va_list_items[$vn_list_id]); } } } } } } else { if ($t_item->load($vn_id)) { // id is the id of the parent for the level we're going to return $t_list = new ca_lists($vn_list_id = $t_item->get('list_id')); $vs_label_table_name = $this->opo_item_instance->getLabelTableName(); $vs_label_display_field_name = $this->opo_item_instance->getLabelDisplayField(); $va_list_items = $t_list->getItemsForList($vn_list_id, array('returnHierarchyLevels' => false, 'item_id' => $vn_id, 'extractValuesByUserLocale' => true, 'sort' => $t_list->get('sort_type'), 'directChildrenOnly' => true, 'limit' => $vn_max_items_per_page, 'start' => $vn_start)); // output $va_display_values = caProcessTemplateForIDs($vs_template, 'ca_list_items', array_keys($va_list_items), array('requireLinkTags' => true, 'returnAsArray' => true)); $vn_c = 0; foreach ($va_list_items as $vn_item_id => $va_item) { if ($vn_c >= $vn_start) { unset($va_item['description']); unset($va_item['icon']); if (!$va_item[$vs_label_display_field_name]) { $va_item[$vs_label_display_field_name] = $va_item['idno']; } if (!$va_item[$vs_label_display_field_name]) { $va_item[$vs_label_display_field_name] = '???'; } $va_item['name'] = $va_display_values[$vn_c]; if (!$va_item['name']) { $va_item['name'] = '??? ' . $vn_item_id; } $va_item['table'] = 'ca_list_items'; // Child count is only valid if has_children is not null $va_item['children'] = 0; $va_list_items[$vn_item_id] = $va_item; } $vn_c++; if ($vn_c > $vn_start + $vn_max_items_per_page) { break; } } if (sizeof($va_list_items)) { $o_db = new Db(); $qr_res = $o_db->query("\n\t\t\t\t\t\t\t\tSELECT count(*) c, parent_id\n\t\t\t\t\t\t\t\tFROM ca_list_items\n\t\t\t\t\t\t\t\tWHERE \n\t\t\t\t\t\t\t\t\tparent_id IN (" . join(",", array_keys($va_list_items)) . ") AND deleted = 0\n\t\t\t\t\t\t\t\tGROUP BY parent_id\n\t\t\t\t\t\t\t"); while ($qr_res->nextRow()) { $va_list_items[$qr_res->get('parent_id')]['children'] = $qr_res->get('c'); } } } } $va_list_items_sortable = []; foreach ($va_list_items as $vn_item_id => $va_item) { $va_list_items_sortable[caSortableValue(mb_strtolower(preg_replace('![^A-Za-z0-9]!', '_', caRemoveAccents($va_item['name_plural'])))) . '_' . $vn_item_id] = $va_item; } $va_list_items = $va_list_items_sortable; $va_list_items['_sortOrder'] = array_keys($va_list_items); $va_list_items['_primaryKey'] = $t_item->primaryKey(); // pass the name of the primary key so the hierbrowser knows where to look for item_id's $va_list_items['_itemCount'] = sizeof($va_list_items); //$t_list ? $t_list->numItemsInList() : ($qr_res ? $qr_res->numRows() : 0); $va_level_data[$pn_id] = $va_list_items; } if (!$this->request->getParameter('init', pInteger)) { // only set remember "last viewed" if the load is done interactively // if the GetHierarchyLevel() call is part of the initialization of the hierarchy browser // then all levels are loaded, sometimes out-of-order; if we record these initialization loads // as the 'last viewed' we can end up losing the true 'last viewed' value // // ... so the hierbrowser passes an extra 'init' parameters set to 1 if the GetHierarchyLevel() call // is part of a browser initialization $this->request->session->setVar($this->ops_table_name . '_' . $ps_bundle . '_browse_last_id', $pn_id); } $this->view->setVar('dontShowSymbols', (bool) $this->request->getParameter('noSymbols', pString)); $this->view->setVar('list_item_list', $va_level_data); return $this->render('list_item_hierarchy_level_json.php'); }