Пример #1
0
 /**
  *
  * @param string $type can be one of: ["ca_objects", "ca_entities", "ca_places", "ca_occurrences", "ca_collections", "ca_list_items", "ca_object_representations", "ca_storage_locations", "ca_movements", "ca_loans", "ca_tours", "ca_tour_stops"]
  * @param int $item_id primary key
  * @param string $attribute_code_or_id
  * @return array
  * @throws SoapFault
  */
 public function getAttributesByElement($type, $item_id, $attribute_code_or_id)
 {
     if (!($t_subject_instance = $this->getTableInstance($type, $item_id, true))) {
         throw new SoapFault("Server", "Invalid type or item_id");
     }
     $t_locale = new ca_locales();
     $t_element = new ca_metadata_elements();
     $va_attrs = $t_subject_instance->getAttributesByElement($attribute_code_or_id);
     $va_return = array();
     $va_element_type_cfg = ca_metadata_elements::getAttributeTypes();
     foreach ($va_attrs as $vo_attr) {
         $va_attr = array();
         foreach ($vo_attr->getValues() as $vo_value) {
             $t_element->load($vo_value->getElementID());
             $va_attr[] = array("value_id" => $vo_value->getValueID(), "display_value" => $vo_value->getDisplayValue(), "element_code" => $vo_value->getElementCode(), "element_id" => $vo_value->getElementID(), "attribute_info" => $t_subject_instance->getAttributeLabelAndDescription($vo_value->getElementCode()), "datatype" => $va_element_type_cfg[$t_element->get("datatype")], "locale" => $t_locale->localeIDToCode($vo_attr->getLocaleID()));
         }
         $va_return[$vo_attr->getAttributeID()] = $va_attr;
     }
     return $va_return;
 }
 /**
  * Returns list of caption/subtitle files attached to a representation
  * The return value is an array key'ed on the caption_id; array values are arrays
  * with keys set to values for each file returned. They keys are:
  *		path = The absolute file path to the file
  *		url = The URL for the file
  *		caption_id = a unique identifier for each attached caption file
  *
  * @param int $pn_representation_id The representation_id of the representation to return files for. If omitted the currently loaded representation is used. If no representation_id is specified and no row is loaded null will be returned.
  * @param array $pa_locale_ids 
  * @param array $pa_options
  * @return array A list of caption files attached to the representations. If no files are associated an empty array is returned.
  */
 public function getCaptionFileList($pn_representation_id = null, $pa_locale_ids = null, $pa_options = null)
 {
     if (!($vn_representation_id = $pn_representation_id)) {
         if (!($vn_representation_id = $this->getPrimaryKey())) {
             return null;
         }
     }
     $t_locale = new ca_locales();
     $va_locale_ids = array();
     if ($pa_locale_ids) {
         if (!is_array($pa_locale_ids)) {
             $pa_locale_ids = array($pa_locale_ids);
         }
         foreach ($pa_locale_ids as $vn_i => $vm_locale) {
             if (is_numeric($vm_locale) && (int) $vm_locale) {
                 $va_locale_ids[] = (int) $vm_locale;
             } else {
                 if ($vn_locale_id = $t_locale->localeCodeToID($vm_locale)) {
                     $va_locale_ids[] = $vn_locale_id;
                 }
             }
         }
     }
     $vs_locale_sql = '';
     $va_params = array((int) $vn_representation_id);
     if (sizeof($va_locale_ids) > 0) {
         $vs_locale_sql = " AND locale_id IN (?)";
         $va_params[] = $va_locale_ids;
     }
     $o_db = $this->getDb();
     $qr_res = $o_db->query("\n \t\t\tSELECT *\n \t\t\tFROM ca_object_representation_captions\n \t\t\tWHERE\n \t\t\t\trepresentation_id = ?\n \t\t\t{$vs_locale_sql}\n \t\t", $va_params);
     $va_files = array();
     while ($qr_res->nextRow()) {
         $vn_caption_id = $qr_res->get('caption_id');
         $vn_locale_id = $qr_res->get('locale_id');
         $va_files[$vn_caption_id] = $qr_res->getRow();
         unset($va_files[$vn_caption_id]['caption_file']);
         $va_files[$vn_caption_id]['path'] = $qr_res->getFilePath('caption_file');
         $va_files[$vn_caption_id]['url'] = $qr_res->getFileUrl('caption_file');
         $va_files[$vn_caption_id]['filesize'] = caFormatFileSize(filesize($va_files[$vn_caption_id]['path']));
         $va_files[$vn_caption_id]['caption_id'] = $vn_caption_id;
         $va_files[$vn_caption_id]['locale_id'] = $vn_locale_id;
         $va_files[$vn_caption_id]['locale'] = $t_locale->localeIDToName($vn_locale_id);
         $va_files[$vn_caption_id]['locale_code'] = $t_locale->localeIDToCode($vn_locale_id);
     }
     return $va_files;
 }
 /**
  *
  */
 public function getValuesForExport($pa_options = null)
 {
     $va_data = parent::getValuesForExport($pa_options);
     // get intrinsics and attributes
     $t_locale = new ca_locales();
     $t_list = new ca_lists();
     // get labels
     $va_preferred_labels = $this->get($this->tableName() . ".preferred_labels", array('returnAsArray' => true, 'returnAllLocales' => true));
     if (is_array($va_preferred_labels) && sizeof($va_preferred_labels)) {
         $va_preferred_labels_for_export = array();
         foreach ($va_preferred_labels as $vn_id => $va_labels_by_locale) {
             foreach ($va_labels_by_locale as $vn_locale_id => $va_labels) {
                 if (!($vs_locale = $t_locale->localeIDToCode($vn_locale_id))) {
                     $vs_locale = 'NONE';
                 }
                 $va_preferred_labels_for_export[$vs_locale] = $va_labels[0];
                 unset($va_preferred_labels_for_export[$vs_locale]['form_element']);
             }
         }
         $va_data['preferred_labels'] = $va_preferred_labels_for_export;
     }
     $va_nonpreferred_labels = $this->get($this->tableName() . ".nonpreferred_labels", array('returnAsArray' => true, 'returnAllLocales' => true));
     if (is_array($va_nonpreferred_labels) && sizeof($va_nonpreferred_labels)) {
         $va_nonpreferred_labels_for_export = array();
         foreach ($va_nonpreferred_labels as $vn_id => $va_labels_by_locale) {
             foreach ($va_labels_by_locale as $vn_locale_id => $va_labels) {
                 if (!($vs_locale = $t_locale->localeIDToCode($vn_locale_id))) {
                     $vs_locale = 'NONE';
                 }
                 $va_nonpreferred_labels_for_export[$vs_locale] = $va_labels;
                 foreach ($va_nonpreferred_labels_for_export[$vs_locale] as $vn_i => $va_label) {
                     unset($va_nonpreferred_labels_for_export[$vs_locale][$vn_i]['form_element']);
                 }
             }
         }
         $va_data['nonpreferred_labels'] = $va_nonpreferred_labels_for_export;
     }
     return $va_data;
 }
 /**
  *
  */
 public function DownloadCaptionFile()
 {
     list($pn_representation_id, $t_rep) = $this->_initView();
     $pn_caption_id = $this->request->getParameter('caption_id', pString);
     $this->view->setVar('representation_id', $pn_representation_id);
     $this->view->setVar('caption_id', $pn_caption_id);
     $this->view->setVar('t_object_representation', $t_rep);
     $t_caption = new ca_object_representation_captions($pn_caption_id);
     if (!$t_caption->getPrimaryKey() || (int) $t_caption->get('representation_id') !== (int) $pn_representation_id) {
         die(_t("Invalid caption file"));
     }
     $t_locale = new ca_locales();
     $vn_locale_id = $t_caption->get('locale_id');
     $vs_locale = $t_locale->localeIDToCode($vn_locale_id);
     $this->view->setVar('file_path', $t_caption->getFilePath('caption_file'));
     $va_info = $t_caption->getFileInfo("caption_file");
     switch ($this->request->user->getPreference('downloaded_file_naming')) {
         case 'idno':
             $this->view->setVar('download_name', str_replace(' ', '_', $t_rep->get('idno')) . "_captions_{$vs_locale}.vtt");
             break;
         case 'idno_and_version':
             $this->view->setVar('download_name', str_replace(' ', '_', $t_rep->get('idno')) . "_captions_{$vs_locale}.vtt");
             break;
         case 'idno_and_rep_id_and_version':
             $this->view->setVar('download_name', str_replace(' ', '_', $t_rep->get('idno')) . "_representation_{$pn_representation_id}_captions_{$vs_locale}.vtt");
             break;
         case 'original_name':
         default:
             if ($va_info['ORIGINAL_FILENAME']) {
                 $this->view->setVar('download_name', $va_info['ORIGINAL_FILENAME'] . "_captions_{$vs_locale}.vtt");
             } else {
                 $this->view->setVar('download_name', str_replace(' ', '_', $t_rep->get('idno')) . "_representation_{$pn_representation_id}_captions_{$vs_locale}.vtt");
             }
             break;
     }
     return $this->render('caption_download_binary.php');
 }
Пример #5
0
 /**
  * Returns version of label 'display' field value suitable for sorting
  * The sortable value is the same as the display value except when the display value
  * starts with a definite article ('the' in English) or indefinite article ('a' or 'an' in English)
  * in the locale of the label, in which case the article is moved to the end of the sortable value.
  * 
  * What constitutes an article is defined in the TimeExpressionParser localization files. So if the
  * locale of the label doesn't correspond to an existing TimeExpressionParser localization, then
  * the users' current locale setting is used.
  */
 private function _generateSortableValue()
 {
     if ($vs_sort_field = $this->getProperty('LABEL_SORT_FIELD')) {
         $vs_display_field = $this->getProperty('LABEL_DISPLAY_FIELD');
         $o_tep = new TimeExpressionParser();
         $t_locale = new ca_locales();
         $o_tep->setLanguage($t_locale->localeIDToCode($this->get('locale_id')));
         $o_lang_settings = $o_tep->getLanguageSettings();
         $vs_display_value = trim(preg_replace('![^\\p{L}0-9 ]+!u', ' ', $this->get($vs_display_field)));
         $va_definite_articles = $o_lang_settings->get('definiteArticles');
         $va_indefinite_articles = $o_lang_settings->get('indefiniteArticles');
         foreach (array($o_lang_settings->get('definiteArticles'), $o_lang_settings->get('indefiniteArticles')) as $va_articles) {
             if (is_array($va_articles)) {
                 foreach ($va_articles as $vs_article) {
                     if (preg_match('!^(' . $vs_article . ')[ ]+!i', $vs_display_value, $va_matches)) {
                         $vs_display_value = trim(str_replace($va_matches[1], '', $vs_display_value) . ', ' . $va_matches[1]);
                         break 2;
                     }
                 }
             }
         }
         $this->set($vs_sort_field, $vs_display_value);
     }
 }
 /**
  * Returns list of items in the specified table related to the currently loaded row.
  * 
  * @param $pm_rel_table_name_or_num - the table name or table number of the item type you want to get a list of (eg. if you are calling this on an ca_objects instance passing 'ca_entities' here will get you a list of entities related to the object)
  * @param $pa_options - array of options. Supported options are:
  *
  * 		restrict_to_type = restricts returned items to those of the specified type; only supports a single type which can be specified as a list item_code or item_id
  *		restrictToType = synonym for restrict_to_type
  *		restrict_to_types = restricts returned items to those of the specified types; pass an array of list item_codes or item_ids
  *		restrictToTypes = synonym for restrict_to_types
  *		dont_include_subtypes_in_type_restriction = if set subtypes are not included when enforcing restrict_to_types. Note that restrict_to_relationship_types always includes subtypes in its restriction.
  *		dontIncludeSubtypesInTypeRestriction = synonym for dont_include_subtypes_in_type_restriction
  *		restrict_to_relationship_types = restricts returned items to those related to the current row by the specified relationship type(s). You can pass either an array of types or a single type. The types can be relationship type_code's or type_id's.
  *		restrictToRelationshipTypes = synonym for restrict_to_relationship_types
  *
  * 		restrictToBundleValues = restricts returned items to bundle values in related table. pass an associative array with elements like this: bundle_name => list of values
  *
  *		exclude_relationship_types = omits any items related to the current row with any of the specified types from the returned set of ids. You can pass either an array of types or a single type. The types can be relationship type_code's or type_id's.
  *		excludeRelationshipTypes = synonym for exclude_relationship_types
  * 		exclude_type = excludes returned items of the specified type; only supports a single type which can be specified as a list item_code or item_id
  *		excludeType = synonym for exclude_type
  *		exclude_types = omits any items related to the current row that are of any of the specified types from the returned set of ids. You can pass either an array of types or a single type. The types can be type_code's or type_id's.
  *		excludeTypes = synonym for exclude_types
  *
  *		restrict_to_lists = when fetching related ca_list_items restricts returned items to those that are in the specified lists; pass an array of list list_codes or list_ids
  *		restrictToLists = synonym for restrict_to_lists
  *
  *		fields = array of fields (in table.fieldname format) to include in returned data
  *		return_non_preferred_labels = if set to true, non-preferred labels are included in returned data
  *		returnNonPreferredLabels = synonym for return_non_preferred_labels
  *		checkAccess = array of access values to filter results by; if defined only items with the specified access code(s) are returned
  *		return_labels_as_array = if set to true then all labels associated with row are returned in an array, otherwise only a text value in the current locale is returned; default is false - return single label in current locale
  *		returnLabelsAsArray = synonym for return_labels_as_array
  * 		row_ids = array of primary key values to use when fetching related items; if omitted or set to a null value the 'row_id' option (single value) will be used; if row_id is also not set then the currently loaded primary key value will be used
  *		row_id = primary key value to use when fetching related items; if omitted or set to a false value (eg. null, false, 0) then the currently loaded primary key value is used [default]
  *		start = item to start return set at; first item is numbered zero; default is 0
  *		limit = number of items to limit return set to; default is 1000
  *		sort = optional array of bundles to sort returned values on. Currently only supported when getting related values via simple related <table_name> and <table_name>.related invokations. Eg. from a ca_objects results you can use the 'sort' option got get('ca_entities'), get('ca_entities.related') or get('ca_objects.related'). The bundle specifiers are fields with or without tablename. Only those fields returned for the related tables (intrinsics, label fields and attributes) are sortable.
  *		sortDirection = direction of sort. Valid values as "ASC" (ascending) and "DESC" (descending). Default is ASC.
  *		showDeleted = if set to true, related items that have been deleted are returned. Default is false.
  *		where = optional array of fields and field values to filter returned values on. The fields must be intrinsic and in the same table as the field being "get()'ed" Can be used to filter returned values from primary and related tables. This option can be useful when you want to fetch certain values from a related table. For example, you want to get the relationship source_info values, but only for relationships going to a specific related record. Note that multiple fields/values are effectively AND'ed together - all must match for a row to be returned - and that only equivalence is supported (eg. field equals value).
  *		user_id = If set item level access control is performed relative to specified user_id, otherwise defaults to logged in user
  *		groupFields = Groups together fields in an arrangement that is easier for import to another system. Used by the ItemInfo web service when in "import" mode. Default is false.
  *		returnLocaleCodes = Return locale values as codes (Ex. en_US) rather than numeric database-specific locale_ids. Default is false.
  * @return array - list of related items
  */
 public function getRelatedItems($pm_rel_table_name_or_num, $pa_options = null)
 {
     global $AUTH_CURRENT_USER_ID;
     $vn_user_id = isset($pa_options['user_id']) && $pa_options['user_id'] ? $pa_options['user_id'] : (int) $AUTH_CURRENT_USER_ID;
     $vb_show_if_no_acl = (bool) ($this->getAppConfig()->get('default_item_access_level') > __CA_ACL_NO_ACCESS__);
     // convert options
     if (isset($pa_options['restrictToType']) && (!isset($pa_options['restrict_to_type']) || !$pa_options['restrict_to_type'])) {
         $pa_options['restrict_to_type'] = $pa_options['restrictToType'];
     }
     if (isset($pa_options['restrictToTypes']) && (!isset($pa_options['restrict_to_types']) || !$pa_options['restrict_to_types'])) {
         $pa_options['restrict_to_types'] = $pa_options['restrictToTypes'];
     }
     if (isset($pa_options['restrictToRelationshipTypes']) && (!isset($pa_options['restrict_to_relationship_types']) || !$pa_options['restrict_to_relationship_types'])) {
         $pa_options['restrict_to_relationship_types'] = $pa_options['restrictToRelationshipTypes'];
     }
     if (isset($pa_options['excludeType']) && (!isset($pa_options['exclude_type']) || !$pa_options['exclude_type'])) {
         $pa_options['exclude_type'] = $pa_options['excludeType'];
     }
     if (isset($pa_options['excludeTypes']) && (!isset($pa_options['exclude_types']) || !$pa_options['exclude_types'])) {
         $pa_options['exclude_types'] = $pa_options['excludeTypes'];
     }
     if (isset($pa_options['excludeRelationshipTypes']) && (!isset($pa_options['exclude_relationship_types']) || !$pa_options['exclude_relationship_types'])) {
         $pa_options['exclude_relationship_types'] = $pa_options['excludeRelationshipTypes'];
     }
     if (isset($pa_options['dontIncludeSubtypesInTypeRestriction']) && (!isset($pa_options['dont_include_subtypes_in_type_restriction']) || !$pa_options['dont_include_subtypes_in_type_restriction'])) {
         $pa_options['dont_include_subtypes_in_type_restriction'] = $pa_options['dontIncludeSubtypesInTypeRestriction'];
     }
     if (isset($pa_options['returnNonPreferredLabels']) && (!isset($pa_options['return_non_preferred_labels']) || !$pa_options['return_non_preferred_labels'])) {
         $pa_options['return_non_preferred_labels'] = $pa_options['returnNonPreferredLabels'];
     }
     if (isset($pa_options['returnLabelsAsArray']) && (!isset($pa_options['return_labels_as_array']) || !$pa_options['return_labels_as_array'])) {
         $pa_options['return_labels_as_array'] = $pa_options['returnLabelsAsArray'];
     }
     if (isset($pa_options['restrictToLists']) && (!isset($pa_options['restrict_to_lists']) || !$pa_options['restrict_to_lists'])) {
         $pa_options['restrict_to_lists'] = $pa_options['restrictToLists'];
     }
     if (isset($pa_options['groupFields'])) {
         $pa_options['groupFields'] = (bool) $pa_options['groupFields'];
     } else {
         $pa_options['groupFields'] = false;
     }
     $o_db = $this->getDb();
     $t_locale = new ca_locales();
     $o_tep = new TimeExpressionParser();
     $vb_uses_effective_dates = false;
     $va_get_where = isset($pa_options['where']) && is_array($pa_options['where']) && sizeof($pa_options['where']) ? $pa_options['where'] : null;
     $va_row_ids = isset($pa_options['row_ids']) && is_array($pa_options['row_ids']) ? $pa_options['row_ids'] : null;
     $vn_row_id = isset($pa_options['row_id']) && $pa_options['row_id'] ? $pa_options['row_id'] : $this->getPrimaryKey();
     if (isset($pa_options['sort']) && !is_array($pa_options['sort'])) {
         $pa_options['sort'] = array($pa_options['sort']);
     }
     $va_sort_fields = isset($pa_options['sort']) && is_array($pa_options['sort']) ? $pa_options['sort'] : null;
     $vs_sort_direction = isset($pa_options['sortDirection']) && $pa_options['sortDirection'] ? $pa_options['sortDirection'] : null;
     if (!$va_row_ids && $vn_row_id > 0) {
         $va_row_ids = array($vn_row_id);
     }
     if (!$va_row_ids || !is_array($va_row_ids) || !sizeof($va_row_ids)) {
         return array();
     }
     $vb_return_labels_as_array = isset($pa_options['return_labels_as_array']) && $pa_options['return_labels_as_array'] ? true : false;
     $vn_limit = isset($pa_options['limit']) && (int) $pa_options['limit'] > 0 ? (int) $pa_options['limit'] : 1000;
     $vn_start = isset($pa_options['start']) && (int) $pa_options['start'] > 0 ? (int) $pa_options['start'] : 0;
     if (is_numeric($pm_rel_table_name_or_num)) {
         if (!($vs_related_table_name = $this->getAppDataModel()->getTableName($pm_rel_table_name_or_num))) {
             return null;
         }
     } else {
         if (sizeof($va_tmp = explode(".", $pm_rel_table_name_or_num)) > 1) {
             $pm_rel_table_name_or_num = array_shift($va_tmp);
         }
         if (!($o_instance = $this->getAppDataModel()->getInstanceByTableName($pm_rel_table_name_or_num, true))) {
             return null;
         }
         $vs_related_table_name = $pm_rel_table_name_or_num;
     }
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     switch (sizeof($va_path = array_keys($this->getAppDatamodel()->getPath($this->tableName(), $vs_related_table_name)))) {
         case 3:
             $t_item_rel = $this->getAppDatamodel()->getTableInstance($va_path[1]);
             $t_rel_item = $this->getAppDatamodel()->getTableInstance($va_path[2]);
             $vs_key = $t_item_rel->primaryKey();
             //'relation_id';
             break;
         case 2:
             $t_item_rel = null;
             $t_rel_item = $this->getAppDatamodel()->getTableInstance($va_path[1]);
             $vs_key = $t_rel_item->primaryKey();
             break;
         default:
             // bad related table
             return null;
             break;
     }
     // check for self relationship
     $vb_self_relationship = false;
     if ($this->tableName() == $vs_related_table_name) {
         $vb_self_relationship = true;
         $t_rel_item = $this->getAppDatamodel()->getTableInstance($va_path[0]);
         $t_item_rel = $this->getAppDatamodel()->getTableInstance($va_path[1]);
     }
     $va_wheres = array();
     $va_selects = array();
     $va_joins_post_add = array();
     $vs_related_table = $t_rel_item->tableName();
     if ($t_rel_item->hasField('type_id')) {
         $va_selects[] = $vs_related_table . '.type_id item_type_id';
     }
     if ($t_rel_item->hasField('source_id')) {
         $va_selects[] = $vs_related_table . '.source_id item_source_id';
     }
     // TODO: get these field names from models
     if ($t_item_rel) {
         //define table names
         $vs_linking_table = $t_item_rel->tableName();
         $va_selects[] = $vs_related_table . '.' . $t_rel_item->primaryKey();
         // include dates in returned data
         if ($t_item_rel->hasField('effective_date')) {
             $va_selects[] = $vs_linking_table . '.sdatetime';
             $va_selects[] = $vs_linking_table . '.edatetime';
             $vb_uses_effective_dates = true;
         }
         if ($t_rel_item->hasField('is_enabled')) {
             $va_selects[] = $vs_related_table . '.is_enabled';
         }
         if ($t_item_rel->hasField('type_id')) {
             $va_selects[] = $vs_linking_table . '.type_id relationship_type_id';
             require_once __CA_MODELS_DIR__ . '/ca_relationship_types.php';
             $t_rel = new ca_relationship_types();
             $vb_uses_relationship_types = true;
         }
         // limit related items to a specific type
         if ($vb_uses_relationship_types && isset($pa_options['restrict_to_relationship_types']) && $pa_options['restrict_to_relationship_types']) {
             if (!is_array($pa_options['restrict_to_relationship_types'])) {
                 $pa_options['restrict_to_relationship_types'] = array($pa_options['restrict_to_relationship_types']);
             }
             if (sizeof($pa_options['restrict_to_relationship_types'])) {
                 $va_rel_types = array();
                 foreach ($pa_options['restrict_to_relationship_types'] as $vm_type) {
                     if (!$vm_type) {
                         continue;
                     }
                     if (!($vn_type_id = $t_rel->getRelationshipTypeID($vs_linking_table, $vm_type))) {
                         $vn_type_id = (int) $vm_type;
                     }
                     if ($vn_type_id > 0) {
                         $va_rel_types[] = $vn_type_id;
                         if (is_array($va_children = $t_rel->getHierarchyChildren($vn_type_id, array('idsOnly' => true)))) {
                             $va_rel_types = array_merge($va_rel_types, $va_children);
                         }
                     }
                 }
                 if (sizeof($va_rel_types)) {
                     $va_wheres[] = '(' . $vs_linking_table . '.type_id IN (' . join(',', $va_rel_types) . '))';
                 }
             }
         }
         if ($vb_uses_relationship_types && isset($pa_options['exclude_relationship_types']) && $pa_options['exclude_relationship_types']) {
             if (!is_array($pa_options['exclude_relationship_types'])) {
                 $pa_options['exclude_relationship_types'] = array($pa_options['exclude_relationship_types']);
             }
             if (sizeof($pa_options['exclude_relationship_types'])) {
                 $va_rel_types = array();
                 foreach ($pa_options['exclude_relationship_types'] as $vm_type) {
                     if ($vn_type_id = $t_rel->getRelationshipTypeID($vs_linking_table, $vm_type)) {
                         $va_rel_types[] = $vn_type_id;
                         if (is_array($va_children = $t_rel->getHierarchyChildren($vn_type_id, array('idsOnly' => true)))) {
                             $va_rel_types = array_merge($va_rel_types, $va_children);
                         }
                     }
                 }
                 if (sizeof($va_rel_types)) {
                     $va_wheres[] = '(' . $vs_linking_table . '.type_id NOT IN (' . join(',', $va_rel_types) . '))';
                 }
             }
         }
     }
     // limit related items to a specific type
     if (isset($pa_options['restrict_to_type']) && $pa_options['restrict_to_type']) {
         if (!isset($pa_options['restrict_to_types']) || !is_array($pa_options['restrict_to_types'])) {
             $pa_options['restrict_to_types'] = array();
         }
         $pa_options['restrict_to_types'][] = $pa_options['restrict_to_type'];
     }
     $va_type_ids = caMergeTypeRestrictionLists($t_rel_item, $pa_options);
     if (is_array($va_type_ids) && sizeof($va_type_ids) > 0) {
         $va_wheres[] = "({$vs_related_table}.type_id IN (" . join(',', $va_type_ids) . ')' . ($t_rel_item->getFieldInfo('type_id', 'IS_NULL') ? " OR ({$vs_related_table}.type_id IS NULL)" : '') . ')';
     }
     $va_source_ids = caMergeSourceRestrictionLists($t_rel_item, $pa_options);
     if (method_exists($t_rel_item, "getSourceFieldName") && ($vs_source_id_fld = $t_rel_item->getSourceFieldName()) && is_array($va_source_ids) && sizeof($va_source_ids) > 0) {
         $va_wheres[] = "({$vs_related_table}.{$vs_source_id_fld} IN (" . join(',', $va_source_ids) . "))";
     }
     if (isset($pa_options['exclude_type']) && $pa_options['exclude_type']) {
         if (!isset($pa_options['exclude_types']) || !is_array($pa_options['exclude_types'])) {
             $pa_options['exclude_types'] = array();
         }
         $pa_options['exclude_types'][] = $pa_options['exclude_type'];
     }
     if (isset($pa_options['exclude_types']) && is_array($pa_options['exclude_types'])) {
         $va_type_ids = caMakeTypeIDList($t_rel_item->tableName(), $pa_options['exclude_types']);
         if (is_array($va_type_ids) && sizeof($va_type_ids) > 0) {
             $va_wheres[] = '(' . $vs_related_table . '.type_id NOT IN (' . join(',', $va_type_ids) . '))';
         }
     }
     if ($this->getAppConfig()->get('perform_item_level_access_checking')) {
         $t_user = new ca_users($vn_user_id, true);
         if (is_array($va_groups = $t_user->getUserGroups()) && sizeof($va_groups)) {
             $va_group_ids = array_keys($va_groups);
         } else {
             $va_group_ids = array();
         }
         // Join to limit what browse table items are used to generate facet
         $va_joins_post_add[] = 'LEFT JOIN ca_acl ON ' . $t_rel_item->tableName() . '.' . $t_rel_item->primaryKey() . ' = ca_acl.row_id AND ca_acl.table_num = ' . $t_rel_item->tableNum() . "\n";
         $va_wheres[] = "(\n\t\t\t\t((\n\t\t\t\t\t(ca_acl.user_id = " . (int) $vn_user_id . ")\n\t\t\t\t\t" . (sizeof($va_group_ids) > 0 ? "OR\n\t\t\t\t\t(ca_acl.group_id IN (" . join(",", $va_group_ids) . "))" : "") . "\n\t\t\t\t\tOR\n\t\t\t\t\t(ca_acl.user_id IS NULL and ca_acl.group_id IS NULL)\n\t\t\t\t) AND ca_acl.access >= " . __CA_ACL_READONLY_ACCESS__ . ")\n\t\t\t\t" . ($vb_show_if_no_acl ? "OR ca_acl.acl_id IS NULL" : "") . "\n\t\t\t)";
     }
     if (is_array($va_get_where)) {
         foreach ($va_get_where as $vs_fld => $vm_val) {
             if ($t_rel_item->hasField($vs_fld)) {
                 $va_wheres[] = "({$vs_related_table_name}.{$vs_fld} = " . (!is_numeric($vm_val) ? "'" . $this->getDb()->escape($vm_val) . "'" : $vm_val) . ")";
             }
         }
     }
     if ($vs_idno_fld = $t_rel_item->getProperty('ID_NUMBERING_ID_FIELD')) {
         $va_selects[] = $t_rel_item->tableName() . '.' . $vs_idno_fld;
     }
     if ($vs_idno_sort_fld = $t_rel_item->getProperty('ID_NUMBERING_SORT_FIELD')) {
         $va_selects[] = $t_rel_item->tableName() . '.' . $vs_idno_sort_fld;
     }
     $va_selects[] = $va_path[1] . '.' . $vs_key;
     if (isset($pa_options['fields']) && is_array($pa_options['fields'])) {
         $va_selects = array_merge($va_selects, $pa_options['fields']);
     }
     // if related item is labelable then include the label table in the query as well
     $vs_label_display_field = null;
     if (method_exists($t_rel_item, "getLabelTableName")) {
         if ($vs_label_table_name = $t_rel_item->getLabelTableName()) {
             // make sure it actually has a label table...
             $va_path[] = $vs_label_table_name;
             $t_rel_item_label = $this->getAppDatamodel()->getTableInstance($vs_label_table_name);
             $vs_label_display_field = $t_rel_item_label->getDisplayField();
             if ($vb_return_labels_as_array || is_array($va_sort_fields) && sizeof($va_sort_fields)) {
                 $va_selects[] = $vs_label_table_name . '.*';
             } else {
                 $va_selects[] = $vs_label_table_name . '.' . $vs_label_display_field;
                 $va_selects[] = $vs_label_table_name . '.locale_id';
                 if ($t_rel_item_label->hasField('surname')) {
                     // hack to include fields we need to sort entity labels properly
                     $va_selects[] = $vs_label_table_name . '.surname';
                     $va_selects[] = $vs_label_table_name . '.forename';
                 }
             }
             if ($t_rel_item_label->hasField('is_preferred') && (!isset($pa_options['return_non_preferred_labels']) || !$pa_options['return_non_preferred_labels'])) {
                 $va_wheres[] = "(" . $vs_label_table_name . '.is_preferred = 1)';
             }
         }
     }
     // return source info in returned data
     if ($t_item_rel && $t_item_rel->hasField('source_info')) {
         $va_selects[] = $vs_linking_table . '.source_info';
     }
     if (isset($pa_options['checkAccess']) && is_array($pa_options['checkAccess']) && sizeof($pa_options['checkAccess']) && $t_rel_item->hasField('access')) {
         $va_wheres[] = "(" . $t_rel_item->tableName() . '.access IN (' . join(',', $pa_options['checkAccess']) . '))';
     }
     if ((!isset($pa_options['showDeleted']) || !$pa_options['showDeleted']) && $t_rel_item->hasField('deleted')) {
         $va_wheres[] = "(" . $t_rel_item->tableName() . '.deleted = 0)';
     }
     if ($vb_self_relationship) {
         //
         // START - self relation
         //
         $va_rel_info = $this->getAppDatamodel()->getRelationships($va_path[0], $va_path[1]);
         if ($vs_label_table_name) {
             $va_label_rel_info = $this->getAppDatamodel()->getRelationships($va_path[0], $vs_label_table_name);
         }
         $va_rels = array();
         $vn_i = 0;
         foreach ($va_rel_info[$va_path[0]][$va_path[1]] as $va_possible_keys) {
             $va_joins = array();
             $va_joins[] = "INNER JOIN " . $va_path[1] . " ON " . $va_path[1] . '.' . $va_possible_keys[1] . ' = ' . $va_path[0] . '.' . $va_possible_keys[0] . "\n";
             if ($vs_label_table_name) {
                 $va_joins[] = "INNER JOIN " . $vs_label_table_name . " ON " . $vs_label_table_name . '.' . $va_label_rel_info[$va_path[0]][$vs_label_table_name][0][1] . ' = ' . $va_path[0] . '.' . $va_label_rel_info[$va_path[0]][$vs_label_table_name][0][0] . "\n";
             }
             $vs_other_field = $vn_i == 0 ? $va_rel_info[$va_path[0]][$va_path[1]][1][1] : $va_rel_info[$va_path[0]][$va_path[1]][0][1];
             $vs_direction = preg_match('!left!', $vs_other_field) ? 'ltor' : 'rtol';
             $va_selects['row_id'] = $va_path[1] . '.' . $vs_other_field . ' AS row_id';
             $vs_order_by = '';
             $vs_sort_fld = '';
             if ($t_item_rel && $t_item_rel->hasField('rank')) {
                 $vs_order_by = ' ORDER BY ' . $t_item_rel->tableName() . '.rank';
                 $vs_sort_fld = 'rank';
                 $va_selects[] = $t_item_rel->tableName() . ".rank";
             } else {
                 if ($t_rel_item && ($vs_sort = $t_rel_item->getProperty('ID_NUMBERING_SORT_FIELD'))) {
                     $vs_order_by = " ORDER BY " . $t_rel_item->tableName() . ".{$vs_sort}";
                     $vs_sort_fld = $vs_sort;
                     $va_selects[] = $t_rel_item->tableName() . ".{$vs_sort}";
                 }
             }
             $vs_sql = "\n\t\t\t\t\tSELECT " . join(', ', $va_selects) . "\n\t\t\t\t\tFROM " . $va_path[0] . "\n\t\t\t\t\t" . join("\n", array_merge($va_joins, $va_joins_post_add)) . "\n\t\t\t\t\tWHERE\n\t\t\t\t\t\t" . join(' AND ', array_merge($va_wheres, array('(' . $va_path[1] . '.' . $vs_other_field . ' IN (' . join(',', $va_row_ids) . '))'))) . "\n\t\t\t\t\t{$vs_order_by}";
             //print "<pre>$vs_sql</pre>\n";
             $qr_res = $o_db->query($vs_sql);
             if ($vb_uses_relationship_types) {
                 $va_rel_types = $t_rel->getRelationshipInfo($va_path[1]);
             }
             $vn_c = 0;
             if ($vn_start > 0) {
                 $qr_res->seek($vn_start);
             }
             while ($qr_res->nextRow()) {
                 if ($vn_c >= $vn_limit) {
                     break;
                 }
                 $va_row = $qr_res->getRow();
                 $vn_id = $va_row[$vs_key] . '/' . $va_row['row_id'];
                 $vs_sort_key = $qr_res->get($vs_sort_fld);
                 $vs_display_label = $va_row[$vs_label_display_field];
                 //unset($va_row[$vs_label_display_field]);
                 if (!$va_rels[$vs_sort_key][$vn_id]) {
                     $va_rels[$vs_sort_key][$vn_id] = $qr_res->getRow();
                 }
                 if ($vb_uses_effective_dates) {
                     // return effective dates as display/parse-able text
                     if ($va_rels[$vs_sort_key][$vn_id]['sdatetime'] || $va_rels[$vs_sort_key][$vn_id]['edatetime']) {
                         $o_tep->setHistoricTimestamps($va_rels[$vs_sort_key][$vn_id]['sdatetime'], $va_rels[$vs_sort_key][$vn_id]['edatetime']);
                         $va_rels[$vs_sort_key][$vn_id]['effective_date'] = $o_tep->getText();
                     }
                 }
                 $vn_locale_id = $qr_res->get('locale_id');
                 if (isset($pa_options['returnLocaleCodes']) && $pa_options['returnLocaleCodes']) {
                     $va_rels[$vs_v]['locale_id'] = $vn_locale_id = $t_locale->localeIDToCode($vn_locale_id);
                 }
                 $va_rels[$vs_sort_key][$vn_id]['labels'][$vn_locale_id] = $vb_return_labels_as_array ? $va_row : $vs_display_label;
                 $va_rels[$vs_sort_key][$vn_id]['_key'] = $vs_key;
                 $va_rels[$vs_sort_key][$vn_id]['direction'] = $vs_direction;
                 $vn_c++;
                 if ($vb_uses_relationship_types) {
                     $va_rels[$vs_sort_key][$vn_id]['relationship_typename'] = $vs_direction == 'ltor' ? $va_rel_types[$va_row['relationship_type_id']]['typename'] : $va_rel_types[$va_row['relationship_type_id']]['typename_reverse'];
                     $va_rels[$vs_sort_key][$vn_id]['relationship_type_code'] = $va_rel_types[$va_row['relationship_type_id']]['type_code'];
                 }
                 //
                 // Return data in an arrangement more convenient for the data importer
                 //
                 if ($pa_options['groupFields']) {
                     $vs_rel_pk = $t_rel_item->primaryKey();
                     if ($t_rel_item_label) {
                         foreach ($t_rel_item_label->getFormFields() as $vs_field => $va_field_info) {
                             if (!isset($va_rels[$vs_v][$vs_field]) || $vs_field == $vs_rel_pk) {
                                 continue;
                             }
                             $va_rels[$vs_v]['preferred_labels'][$vs_field] = $va_rels[$vs_v][$vs_field];
                             unset($va_rels[$vs_v][$vs_field]);
                         }
                     }
                     foreach ($t_rel_item->getFormFields() as $vs_field => $va_field_info) {
                         if (!isset($va_rels[$vs_v][$vs_field]) || $vs_field == $vs_rel_pk) {
                             continue;
                         }
                         $va_rels[$vs_v]['intrinsic'][$vs_field] = $va_rels[$vs_v][$vs_field];
                         unset($va_rels[$vs_v][$vs_field]);
                     }
                     unset($va_rels[$vs_v]['_key']);
                     unset($va_rels[$vs_v]['row_id']);
                 }
             }
             $vn_i++;
         }
         ksort($va_rels);
         // sort by sort key... we'll remove the sort key in the next loop while we add the labels
         // Set 'label' entry - display label in current user's locale
         $va_sorted_rels = array();
         foreach ($va_rels as $vs_sort_key => $va_rels_by_sort_key) {
             foreach ($va_rels_by_sort_key as $vn_id => $va_rel) {
                 $va_tmp = array(0 => $va_rel['labels']);
                 $va_sorted_rels[$vn_id] = $va_rel;
                 $va_values_filtered_by_locale = caExtractValuesByUserLocale($va_tmp);
                 $va_sorted_rels[$vn_id]['label'] = array_shift($va_values_filtered_by_locale);
             }
         }
         $va_rels = $va_sorted_rels;
         //
         // END - self relation
         //
     } else {
         //
         // BEGIN - non-self relation
         //
         $va_wheres[] = "(" . $this->tableName() . '.' . $this->primaryKey() . " IN (" . join(",", $va_row_ids) . "))";
         $vs_cur_table = array_shift($va_path);
         $va_joins = array();
         // Enforce restrict_to_lists for related list items
         if ($vs_related_table_name == 'ca_list_items' && is_array($pa_options['restrict_to_lists'])) {
             $va_list_ids = array();
             foreach ($pa_options['restrict_to_lists'] as $vm_list) {
                 if ($vn_list_id = ca_lists::getListID($vm_list)) {
                     $va_list_ids[] = $vn_list_id;
                 }
             }
             if (sizeof($va_list_ids)) {
                 $va_wheres[] = "(ca_list_items.list_id IN (" . join(",", $va_list_ids) . "))";
             }
         }
         foreach ($va_path as $vs_join_table) {
             $va_rel_info = $this->getAppDatamodel()->getRelationships($vs_cur_table, $vs_join_table);
             $va_joins[] = 'INNER JOIN ' . $vs_join_table . ' ON ' . $vs_cur_table . '.' . $va_rel_info[$vs_cur_table][$vs_join_table][0][0] . ' = ' . $vs_join_table . '.' . $va_rel_info[$vs_cur_table][$vs_join_table][0][1] . "\n";
             $vs_cur_table = $vs_join_table;
         }
         // If we're getting ca_set_items, we can't rename our primary key "row_id" because that table
         // has a field called row_id and it's important and should be in the selected fields. Hence, this hack.
         if ($vs_related_table_name == 'ca_set_items') {
             $va_selects[] = $this->tableName() . '.' . $this->primaryKey();
             $va_selects[] = 'ca_set_items.row_id';
         } else {
             $va_selects[] = $this->tableName() . '.' . $this->primaryKey() . ' AS row_id';
         }
         $vs_order_by = '';
         if ($t_item_rel && $t_item_rel->hasField('rank')) {
             $vs_order_by = ' ORDER BY ' . $t_item_rel->tableName() . '.rank';
         } else {
             if ($t_rel_item && ($vs_sort = $t_rel_item->getProperty('ID_NUMBERING_SORT_FIELD'))) {
                 $vs_order_by = " ORDER BY " . $t_rel_item->tableName() . ".{$vs_sort}";
             }
         }
         $vs_sql = "\n\t\t\t\tSELECT DISTINCT " . join(', ', $va_selects) . "\n\t\t\t\tFROM " . $this->tableName() . "\n\t\t\t\t" . join("\n", array_merge($va_joins, $va_joins_post_add)) . "\n\t\t\t\tWHERE\n\t\t\t\t\t" . join(' AND ', $va_wheres) . "\n\t\t\t\t{$vs_order_by}\n\t\t\t";
         //print "<pre>$vs_sql</pre>\n";
         $qr_res = $o_db->query($vs_sql);
         if ($vb_uses_relationship_types) {
             $va_rel_types = $t_rel->getRelationshipInfo($t_item_rel->tableName());
             $vs_left_table = $t_item_rel->getLeftTableName();
             $vs_direction = $vs_left_table == $this->tableName() ? 'ltor' : 'rtol';
         }
         $va_rels = array();
         $vn_c = 0;
         if ($vn_start > 0) {
             $qr_res->seek($vn_start);
         }
         while ($qr_res->nextRow()) {
             if ($vn_c >= $vn_limit) {
                 break;
             }
             if (isset($pa_options['returnAsSearchResult']) && $pa_options['returnAsSearchResult']) {
                 $va_rels[] = $qr_res->get($t_rel_item->primaryKey());
                 continue;
             }
             $va_row = $qr_res->getRow();
             $vs_v = $va_row[$vs_key];
             $vs_display_label = $va_row[$vs_label_display_field];
             //unset($va_row[$vs_label_display_field]);
             if (!isset($va_rels[$vs_v]) || !$va_rels[$vs_v]) {
                 $va_rels[$vs_v] = $va_row;
             }
             if ($vb_uses_effective_dates) {
                 // return effective dates as display/parse-able text
                 if ($va_rels[$vs_v]['sdatetime'] || $va_rels[$vs_v]['edatetime']) {
                     $o_tep->setHistoricTimestamps($va_rels[$vs_v]['sdatetime'], $va_rels[$vs_v]['edatetime']);
                     $va_rels[$vs_v]['effective_date'] = $o_tep->getText();
                 }
             }
             $vn_locale_id = $qr_res->get('locale_id');
             if (isset($pa_options['returnLocaleCodes']) && $pa_options['returnLocaleCodes']) {
                 $va_rels[$vs_v]['locale_id'] = $vn_locale_id = $t_locale->localeIDToCode($vn_locale_id);
             }
             $va_rels[$vs_v]['labels'][$vn_locale_id] = $vb_return_labels_as_array ? $va_row : $vs_display_label;
             $va_rels[$vs_v]['_key'] = $vs_key;
             $va_rels[$vs_v]['direction'] = $vs_direction;
             $vn_c++;
             if ($vb_uses_relationship_types) {
                 $va_rels[$vs_v]['relationship_typename'] = $vs_direction == 'ltor' ? $va_rel_types[$va_row['relationship_type_id']]['typename'] : $va_rel_types[$va_row['relationship_type_id']]['typename_reverse'];
                 $va_rels[$vs_v]['relationship_type_code'] = $va_rel_types[$va_row['relationship_type_id']]['type_code'];
             }
             if ($pa_options['groupFields']) {
                 $vs_rel_pk = $t_rel_item->primaryKey();
                 if ($t_rel_item_label) {
                     foreach ($t_rel_item_label->getFormFields() as $vs_field => $va_field_info) {
                         if (!isset($va_rels[$vs_v][$vs_field]) || $vs_field == $vs_rel_pk) {
                             continue;
                         }
                         $va_rels[$vs_v]['preferred_labels'][$vs_field] = $va_rels[$vs_v][$vs_field];
                         unset($va_rels[$vs_v][$vs_field]);
                     }
                 }
                 foreach ($t_rel_item->getFormFields() as $vs_field => $va_field_info) {
                     if (!isset($va_rels[$vs_v][$vs_field]) || $vs_field == $vs_rel_pk) {
                         continue;
                     }
                     $va_rels[$vs_v]['intrinsic'][$vs_field] = $va_rels[$vs_v][$vs_field];
                     unset($va_rels[$vs_v][$vs_field]);
                 }
                 unset($va_rels[$vs_v]['_key']);
                 unset($va_rels[$vs_v]['row_id']);
             }
         }
         if (!isset($pa_options['returnAsSearchResult']) || !$pa_options['returnAsSearchResult']) {
             // Set 'label' entry - display label in current user's locale
             foreach ($va_rels as $vs_v => $va_rel) {
                 $va_tmp = array(0 => $va_rel['labels']);
                 $va_tmp2 = caExtractValuesByUserLocale($va_tmp);
                 $va_rels[$vs_v]['label'] = array_shift($va_tmp2);
             }
         }
         //
         // END - non-self relation
         //
     }
     // Apply restrictToBundleValues
     $va_filters = caGetOption('restrictToBundleValues', $pa_options, array());
     if (is_array($va_filters) && sizeof($va_filters) > 0) {
         foreach ($va_rels as $vn_pk => $va_related_item) {
             foreach ($va_filters as $vs_filter => $va_filter_vals) {
                 if (!$vs_filter) {
                     continue;
                 }
                 if (!is_array($va_filter_vals)) {
                     $va_filter_vals = array($va_filter_vals);
                 }
                 foreach ($va_filter_vals as $vn_index => $vs_filter_val) {
                     // is value a list attribute idno?
                     $va_tmp = explode('.', $vs_filter);
                     $vs_element = array_pop($va_tmp);
                     if (!is_numeric($vs_filter_val) && (($t_element = $t_rel_item->_getElementInstance($vs_element)) && $t_element->get('datatype') == 3)) {
                         $va_filter_vals[$vn_index] = caGetListItemID($t_element->get('list_id'), $vs_filter_val);
                     }
                 }
                 $t_rel_item->load($va_related_item[$t_rel_item->primaryKey()]);
                 $va_filter_values = $t_rel_item->get($vs_filter, array('returnAsArray' => true, 'alwaysReturnItemID' => true));
                 $vb_keep = false;
                 if (is_array($va_filter_values)) {
                     foreach ($va_filter_values as $vm_filtered_val) {
                         if (!is_array($vm_filtered_val)) {
                             $vm_filtered_val = array($vm_filtered_val);
                         }
                         foreach ($vm_filtered_val as $vs_val) {
                             if (in_array($vs_val, $va_filter_vals)) {
                                 // one match is enough to keep it
                                 $vb_keep = true;
                             }
                         }
                     }
                 }
                 if (!$vb_keep) {
                     unset($va_rels[$vn_pk]);
                 }
             }
         }
     }
     //
     // Sort on fields if specified
     //
     if (is_array($va_sort_fields) && sizeof($va_rels)) {
         $va_ids = array();
         $vs_rel_pk = $t_rel_item->primaryKey();
         foreach ($va_rels as $vn_i => $va_rel) {
             $va_ids[] = $va_rel[$vs_rel_pk];
         }
         // Handle sorting on attribute values
         $vs_rel_pk = $t_rel_item->primaryKey();
         foreach ($va_sort_fields as $vn_x => $vs_sort_field) {
             if ($vs_sort_field == 'relation_id') {
                 // sort by relationship primary key
                 if ($t_item_rel) {
                     $va_sort_fields[$vn_x] = $vs_sort_field = $t_item_rel->tableName() . '.' . $t_item_rel->primaryKey();
                 }
                 continue;
             }
             $va_tmp = explode('.', $vs_sort_field);
             if ($va_tmp[0] == $vs_related_table_name) {
                 $qr_rel = $t_rel_item->makeSearchResult($va_tmp[0], $va_ids);
                 $vs_table = array_shift($va_tmp);
                 $vs_key = join(".", $va_tmp);
                 while ($qr_rel->nextHit()) {
                     $vn_pk_val = $qr_rel->get($vs_table . "." . $vs_rel_pk);
                     foreach ($va_rels as $vn_rel_id => $va_rel) {
                         if ($va_rel[$vs_rel_pk] == $vn_pk_val) {
                             $va_rels[$vn_rel_id][$vs_key] = $qr_rel->get($vs_sort_field, array("delimiter" => ";", 'sortable' => 1));
                             break;
                         }
                     }
                 }
             }
         }
         // Perform sort
         $va_rels = caSortArrayByKeyInValue($va_rels, $va_sort_fields, $vs_sort_direction);
     }
     return $va_rels;
 }
 public function getDisplaysAsXML()
 {
     $t_display = new ca_bundle_displays();
     /** @var Datamodel $o_dm */
     $o_dm = Datamodel::load();
     $this->opt_locale = new ca_locales();
     $va_displays = $t_display->getBundleDisplays();
     $vs_buf = "<displays>\n";
     foreach ($va_displays as $vn_i => $va_display_by_locale) {
         $va_locales = array_keys($va_display_by_locale);
         $va_info = $va_display_by_locale[$va_locales[0]];
         if (!$t_display->load($va_info['display_id'])) {
             continue;
         }
         $vs_buf .= "\t<display code='" . ($va_info['display_code'] && preg_match('!^[A-Za-z0-9_]+$!', $va_info['display_code']) ? $va_info['display_code'] : 'display_' . $va_info['display_id']) . "' type='" . $o_dm->getTableName($va_info['table_num']) . "' system='" . $t_display->get('is_system') . "'>\n";
         $vs_buf .= "\t\t<labels>\n";
         foreach ($va_display_by_locale as $vn_locale_id => $va_display_info) {
             if (strlen($this->opt_locale->localeIDToCode($vn_locale_id)) > 0) {
                 $vs_buf .= "\t\t\t<label locale='" . $this->opt_locale->localeIDToCode($vn_locale_id) . "'><name>" . caEscapeForXML($va_display_info['name']) . "</name></label>\n";
             }
         }
         $vs_buf .= "\t\t</labels>\n";
         $va_settings = $t_display->getSettings();
         if (sizeof($va_settings) > 0) {
             $vs_buf .= "\t\t<settings>\n";
             foreach ($va_settings as $vs_setting => $vm_val) {
                 if (is_array($vm_val)) {
                     foreach ($vm_val as $vn_i => $vn_val) {
                         $vs_buf .= "\t\t\t<setting name='{$vs_setting}'><![CDATA[" . $vn_val . "]]></setting>\n";
                     }
                 } else {
                     $vs_buf .= "\t\t\t<setting name='{$vs_setting}'><![CDATA[" . $vm_val . "]]></setting>\n";
                 }
             }
             $vs_buf .= "\t\t</settings>\n";
         }
         // User and group access
         $va_users = $t_display->getUsers();
         if (sizeof($va_users) > 0) {
             $vs_buf .= "\t\t<userAccess>\n";
             foreach ($va_users as $va_user_info) {
                 $vs_buf .= "\t\t\t<permission user='******' access='" . $this->_convertUserGroupAccessToString(intval($va_user_info['access'])) . "'/>\n";
             }
             $vs_buf .= "\t\t</userAccess>\n";
         }
         $va_groups = $t_display->getUserGroups();
         if (sizeof($va_groups) > 0) {
             $vs_buf .= "\t\t<groupAccess>\n";
             foreach ($va_groups as $va_group_info) {
                 $vs_buf .= "\t\t\t<permission group='" . $va_group_info["code"] . "' access='" . $this->_convertUserGroupAccessToString(intval($va_group_info['access'])) . "'/>\n";
             }
             $vs_buf .= "\t\t</groupAccess>\n";
         }
         $va_placements = $t_display->getPlacements();
         $vs_buf .= "<bundlePlacements>\n";
         foreach ($va_placements as $vn_placement_id => $va_placement_info) {
             $vs_buf .= "\t\t<placement code='" . preg_replace("![^A-Za-z0-9_]+!", "_", $va_placement_info['bundle_name']) . "'><bundle>" . $va_placement_info['bundle_name'] . "</bundle>\n";
             $va_settings = caUnserializeForDatabase($va_placement_info['settings']);
             if (is_array($va_settings)) {
                 $vs_buf .= "<settings>\n";
                 foreach ($va_settings as $vs_setting => $vm_value) {
                     switch ($vs_setting) {
                         case 'label':
                             if (is_array($vm_value)) {
                                 foreach ($vm_value as $vn_locale_id => $vm_locale_specific_value) {
                                     if (preg_match("/^[a-z]{2,3}\\_[A-Z]{2,3}\$/", $vn_locale_id)) {
                                         // locale code
                                         $vs_locale_code = $vn_locale_id;
                                     } else {
                                         if (!($vs_locale_code = $this->opt_locale->localeIDToCode($vn_locale_id))) {
                                             $vs_locale_code = 'en_US';
                                         }
                                     }
                                     $vs_buf .= "<setting name='label' locale='" . $vs_locale_code . "'>" . caEscapeForXML($vm_locale_specific_value) . "</setting>\n";
                                 }
                             }
                             break;
                         case 'restrict_to_relationship_types':
                             if (is_array($vm_value)) {
                                 foreach ($vm_value as $vn_val) {
                                     $t_rel_type = new ca_relationship_types($vn_val);
                                     if ($t_rel_type->getPrimaryKey()) {
                                         $vs_value = $t_rel_type->get('type_code');
                                         $vs_buf .= "\t\t\t\t<setting name='{$vs_setting}'><![CDATA[" . $vs_value . "]]></setting>\n";
                                     }
                                 }
                             }
                             break;
                         case 'restrict_to_types':
                             if (is_array($vm_value)) {
                                 foreach ($vm_value as $vn_val) {
                                     $t_item = new ca_list_items($vn_val);
                                     if ($t_item->getPrimaryKey()) {
                                         $vs_value = $t_item->get('idno');
                                         $vs_buf .= "\t\t\t\t<setting name='{$vs_setting}'><![CDATA[" . $vs_value . "]]></setting>\n";
                                     }
                                 }
                             }
                             break;
                         default:
                             if (is_array($vm_value)) {
                                 foreach ($vm_value as $vn_i => $vn_val) {
                                     $vs_buf .= "\t\t\t\t<setting name='{$vs_setting}'><![CDATA[" . $vn_val . "]]></setting>\n";
                                 }
                             } else {
                                 $vs_buf .= "\t\t\t\t<setting name='{$vs_setting}'><![CDATA[" . $vm_value . "]]></setting>\n";
                             }
                             break;
                     }
                 }
                 $vs_buf .= "</settings>\n";
             }
             $vs_buf .= "\t\t</placement>\n";
         }
         $vs_buf .= "</bundlePlacements>\n";
         $vs_buf .= "\t</display>\n";
     }
     $vs_buf .= "</displays>\n";
     return $vs_buf;
 }
Пример #8
0
 /**
  *
  * @param string $type can be one of: ["ca_tours", "ca_tour_stops"]
  * @param int $item_id primary key
  * @param string $attribute_code_or_id
  * @return array
  * @throws SoapFault
  */
 public function getAttributesByElement($type, $item_id, $attribute_code_or_id)
 {
     if (!($t_subject_instance = $this->getTableInstance($type, $item_id, true))) {
         throw new SoapFault("Server", "Invalid type or item_id");
     }
     $t_locale = new ca_locales();
     $va_attrs = $t_subject_instance->getAttributesByElement($attribute_code_or_id);
     $va_return = array();
     foreach ($va_attrs as $vo_attr) {
         $va_attr = array();
         foreach ($vo_attr->getValues() as $vo_value) {
             $va_attr[] = array("element_id" => $vo_value->getElementID(), "value_id" => $vo_value->getValueID(), "display_value" => $vo_value->getDisplayValue(), "locale" => $t_locale->localeIDToCode($vo_attr->getLocaleID()));
         }
         $va_return[] = $va_attr;
     }
     return $va_return;
 }
 /**
  *
  */
 public function getValuesForExport($pa_options = null)
 {
     $va_codes = $this->getApplicableElementCodes();
     $va_data = parent::getValuesForExport($pa_options);
     // get intrinsics
     $t_locale = new ca_locales();
     $t_list = new ca_lists();
     // get attributes
     foreach ($va_codes as $vs_code) {
         if ($va_v = $this->get($this->tableName() . '.' . $vs_code, array('returnWithStructure' => true, 'returnAllLocales' => true, 'returnAsArray' => true, 'return' => 'url', 'version' => 'original'))) {
             foreach ($va_v as $vn_id => $va_v_by_locale) {
                 foreach ($va_v_by_locale as $vn_locale_id => $va_v_list) {
                     if (!is_array($va_v_list)) {
                         continue;
                     }
                     if (!($vs_locale = $t_locale->localeIDToCode($vn_locale_id))) {
                         $vs_locale = 'NONE';
                     }
                     $vn_i = 0;
                     foreach ($va_v_list as $vn_index => $va_values) {
                         if (is_array($va_values)) {
                             foreach ($va_values as $vs_sub_code => $vs_value) {
                                 if (!$vs_sub_code) {
                                     continue;
                                 }
                                 if (!($t_element = $this->_getElementInstance($vs_sub_code))) {
                                     continue;
                                 }
                                 switch ((int) $t_element->get('datatype')) {
                                     case 3:
                                         // list
                                         $va_list_item = $t_list->getItemFromListByItemID($t_element->get('list_id'), $vs_value);
                                         $vs_value = $vs_value . ":" . $va_list_item['idno'];
                                         break;
                                 }
                                 $va_data['ca_attribute_' . $vs_code][$vs_locale]['value_' . $vn_i][$vs_sub_code] = $vs_value;
                             }
                             $vn_i++;
                         } else {
                             $va_data['ca_attribute_' . $vs_code][$vs_locale]['value_' . $vn_i][$vs_code] = $va_values;
                         }
                     }
                 }
             }
         }
     }
     return $va_data;
 }
Пример #10
0
 /**
  * Returns version of label 'display' field value suitable for sorting
  * The sortable value is the same as the display value except when the display value
  * starts with a definite article ('the' in English) or indefinite article ('a' or 'an' in English)
  * in the locale of the label, in which case the article is moved to the end of the sortable value.
  * 
  * What constitutes an article is defined in the TimeExpressionParser localization files. So if the
  * locale of the label doesn't correspond to an existing TimeExpressionParser localization, then
  * the users' current locale setting is used.
  */
 private function _generateSortableValue()
 {
     if ($vs_sort_field = $this->getProperty('LABEL_SORT_FIELD')) {
         $vs_display_field = $this->getProperty('LABEL_DISPLAY_FIELD');
         $t_locale = new ca_locales();
         $vs_display_value = caSortableValue($this->get($vs_display_field), array('locale' => $t_locale->localeIDToCode($this->get('locale_id'))));
         $this->set($vs_sort_field, $vs_display_value);
     }
 }