コード例 #1
0
ファイル: BaseModel.php プロジェクト: samrahman/providence
 /**
  * Checks if a relationship exists between the currently loaded row and the specified target
  *
  * @param mixed $pm_rel_table_name_or_num Table name (eg. "ca_entities") or number as defined in datamodel.conf of table containing row to creation relationship to.
  * @param int $pn_rel_id primary key value of row to creation relationship to.
  * @param mixed $pm_type_id Relationship type type_code or type_id, as defined in the ca_relationship_types table. This is required for all relationships that use relationship types. This includes all of the most common types of relationships.
  * @param string $ps_effective_date Optional date expression to qualify relation with. Any expression that the TimeExpressionParser can handle is supported here.
  * @param string $ps_direction Optional direction specification for self-relationships (relationships linking two rows in the same table). Valid values are 'ltor' (left-to-right) and  'rtol' (right-to-left); the direction determines which "side" of the relationship the currently loaded row is on: 'ltor' puts the current row on the left side. For many self-relations the direction determines the nature and display text for the relationship.
  * @param array $pa_options Options are:
  *		relation_id = an optional relation_id to ignore when checking for existence. If you are checking for relations other than one you know exists you can set this to ensure that relationship is not considered.
  *
  * @return mixed Array of matched relation_ids on success, false on error.
  */
 public function relationshipExists($pm_rel_table_name_or_num, $pn_rel_id, $pm_type_id = null, $ps_effective_date = null, $ps_direction = null, $pa_options = null)
 {
     if (!($va_rel_info = $this->_getRelationshipInfo($pm_rel_table_name_or_num))) {
         $this->postError(1240, _t('Related table specification "%1" is not valid', $pm_rel_table_name_or_num), 'BaseModel->addRelationship()');
         return false;
     }
     $vn_relation_id = isset($pa_options['relation_id']) && (int) $pa_options['relation_id'] ? (int) $pa_options['relation_id'] : null;
     $vs_relation_id_sql = null;
     $t_item_rel = $va_rel_info['t_item_rel'];
     if ($pm_type_id && !is_numeric($pm_type_id)) {
         $t_rel_type = new ca_relationship_types();
         if ($vs_linking_table = $t_rel_type->getRelationshipTypeTable($this->tableName(), $t_item_rel->tableName())) {
             $pn_type_id = $t_rel_type->getRelationshipTypeID($vs_linking_table, $pm_type_id);
         }
     } else {
         $pn_type_id = $pm_type_id;
     }
     if (!is_numeric($pn_rel_id)) {
         if ($t_rel_item = $this->_DATAMODEL->getInstanceByTableName($va_rel_info['related_table_name'], true)) {
             if ($this->inTransaction()) {
                 $t_rel_item->setTransaction($this->getTransaction());
             }
             if (($vs_idno_fld = $t_rel_item->getProperty('ID_NUMBERING_ID_FIELD')) && $t_rel_item->load(array($vs_idno_fld => $pn_rel_id))) {
                 $pn_rel_id = $t_rel_item->getPrimaryKey();
             }
         }
     }
     $va_query_params = array();
     $o_db = $this->getDb();
     if (($t_item_rel = $va_rel_info['t_item_rel']) && method_exists($t_item_rel, 'getLeftTableName')) {
         $vs_rel_table_name = $t_item_rel->tableName();
         $vs_type_sql = $vs_timestamp_sql = '';
         $vs_left_table_name = $t_item_rel->getLeftTableName();
         $vs_left_field_name = $t_item_rel->getLeftTableFieldName();
         $vs_right_table_name = $t_item_rel->getRightTableName();
         $vs_right_field_name = $t_item_rel->getRightTableFieldName();
         if ($va_rel_info['related_table_name'] == $this->tableName()) {
             // is self relation
             if ($ps_direction == 'rtol') {
                 $vn_left_id = (int) $pn_rel_id;
                 $vn_right_id = (int) $this->getPrimaryKey();
             } else {
                 $vn_left_id = (int) $this->getPrimaryKey();
                 $vn_right_id = (int) $pn_rel_id;
             }
         } else {
             if ($vs_left_table_name == $this->tableName()) {
                 $vn_left_id = (int) $this->getPrimaryKey();
                 $vn_right_id = (int) $pn_rel_id;
             } else {
                 $vn_left_id = (int) $pn_rel_id;
                 $vn_right_id = (int) $this->getPrimaryKey();
             }
         }
         $va_query_params = array($vn_left_id, $vn_right_id);
         if ($t_item_rel->hasField('type_id')) {
             $vs_type_sql = ' AND type_id = ?';
             $va_query_params[] = (int) $pn_type_id;
         }
         if ($ps_effective_date && $t_item_rel->hasField('sdatetime') && ($va_timestamps = caDateToHistoricTimestamps($ps_effective_date))) {
             $vs_timestamp_sql = " AND (sdatetime = ? AND edatetime = ?)";
             $va_query_params[] = (double) $va_timestamps['start'];
             $va_query_params[] = (double) $va_timestamps['end'];
         }
         if ($vn_relation_id) {
             $vs_relation_id_sql = " AND relation_id <> ?";
             $va_query_params[] = $vn_relation_id;
         }
         $qr_res = $o_db->query("\n\t\t\t\tSELECT relation_id\n\t\t\t\tFROM {$vs_rel_table_name}\n\t\t\t\tWHERE\n\t\t\t\t\t{$vs_left_field_name} = ? AND {$vs_right_field_name} = ?\n\t\t\t\t\t{$vs_type_sql} {$vs_timestamp_sql} {$vs_relation_id_sql}\n\t\t\t", $va_query_params);
         $va_ids = $qr_res->getAllFieldValues('relation_id');
         if ($va_rel_info['related_table_name'] == $this->tableName()) {
             $qr_res = $o_db->query("\n\t\t\t\t\tSELECT relation_id\n\t\t\t\t\tFROM {$vs_rel_table_name}\n\t\t\t\t\tWHERE\n\t\t\t\t\t\t{$vs_right_field_name} = ? AND {$vs_left_field_name} = ?\n\t\t\t\t\t\t{$vs_type_sql} {$vs_timestamp_sql} {$vs_relation_id_sql}\n\t\t\t\t", $va_query_params);
             $va_ids += $qr_res->getAllFieldValues('relation_id');
         }
         if (sizeof($va_ids)) {
             return $va_ids;
         }
     } else {
         if (sizeof($va_rel_info['path']) == 2) {
             // many-one rel
             $va_rel_keys = $va_rel_info['rel_keys'];
             $vb_is_one_table = $this->tableName() == $va_rel_keys['one_table'] ? true : false;
             $vs_where_sql = "(ot." . $va_rel_keys['one_table_field'] . " = ?) AND (mt." . $va_rel_keys['many_table_field'] . " = ?)";
             if ($vb_is_one_table) {
                 $va_query_params[] = (int) $this->getPrimaryKey();
                 $va_query_params[] = (int) $pn_rel_id;
             } else {
                 $va_query_params[] = (int) $pn_rel_id;
                 $va_query_params[] = (int) $this->getPrimaryKey();
             }
             $vs_relation_id_fld = $vb_is_one_table ? "mt." . $va_rel_keys['many_table_field'] : "ot." . $va_rel_keys['one_table_field'];
             $qr_res = $o_db->query($x = "\n\t\t\t\t\tSELECT {$vs_relation_id_fld}\n\t\t\t\t\tFROM {$va_rel_keys['one_table']} ot\n\t\t\t\t\tINNER JOIN {$va_rel_keys['many_table']} AS mt ON mt.{$va_rel_keys['many_table_field']} = ot.{$va_rel_keys['one_table_field']}\n\t\t\t\t\tWHERE\n\t\t\t\t\t\t{$vs_where_sql}\n\t\t\t\t", $va_query_params);
             if (sizeof($va_ids = $qr_res->getAllFieldValues($vs_relation_id_fld))) {
                 return $va_ids;
             }
         }
     }
     return false;
 }
コード例 #2
0
 /**
  * Returns instance of many-to-many table using relationship types between two tables
  *
  * @param string $ps_table1 A valid table name
  * @param string $ps_table2 A valid table name
  * @return BaseRelationshipModel An model instance for the table relating the specified tables 
  */
 public static function getRelationshipTypeInstance($ps_table1, $ps_table2)
 {
     $t_rel = new ca_relationship_types();
     if ($vs_table = $t_rel->getRelationshipTypeTable($ps_table1, $ps_table2)) {
         return $t_rel->getAppDatamodel()->getInstanceByTableName($vs_table);
     }
     return null;
 }
コード例 #3
0
 /**
  * Overrides get() to support bundleable-level fields (relationships)
  *
  * Options:
  *		All supported by BaseModelWithAttributes::get() plus:
  *		retrictToRelationshipTypes - array of ca_relationship_types.type_id values to filter related items on. *MUST BE INTEGER TYPE_IDs, NOT type_code's* This limitation is for performance reasons. You have to convert codes to integer type_id's before invoking get
  *		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 and label fields) are sortable. You cannot sort on attributes.
  *		returnAsLink = if true and $ps_field is set to a specific field in a related table, or $ps_field is set to a related table (eg. ca_entities or ca_entities.related) AND the template option is set and returnAllLocales is not set, then returned values will be links. The destination of the link will be the appropriate editor when executed within Providence or the appropriate detail page when executed within Pawtucket or another front-end. Default is false.
  *		returnAsLinkText = text to use a content of HTML link. If omitted the url itself is used as the link content.
  *		returnAsLinkAttributes = array of attributes to include in link <a> tag. Use this to set class, alt and any other link attributes.
  *		returnAsLinkTarget = Optional link target. If any plugin implementing hookGetAsLink() responds to the specified target then the plugin will be used to generate the links rather than CA's default link generator.
  *		filter = optional array of elements to filter returned values on. The element must be part off the container being fetched from. For example, if you're get()'ing a value from a container element (Eg. ca_objects.dates.date_value) you can filter on any other subelement in that container by passing the name of the subelement and a value (Eg. "date_type" => "copyright"). Pass only the name of the subelement, not the full path that includes the table and container element. You can filter on multiple subelements by passing each subelement as a key in the array. Only values that match all filters are returned. You can filter on multiple values for a subelement by passing an array of values rather than a scalar (Eg. "date_type" => array("copyright", "patent")). Values that match *any* of the values will be returned. Only simple equivalance is supported. NOTE: Filters are only available when returnAsArray is set. They will be ignored if returnAsArray is not set.
  */
 public function get($ps_field, $pa_options = null)
 {
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     $vs_template = caGetOption('template', $pa_options, null);
     $vb_return_as_array = caGetOption('returnAsArray', $pa_options, false, array('castTo' => 'bool'));
     $vb_return_as_link = caGetOption('returnAsLink', $pa_options, false, array('castTo' => 'bool'));
     $vs_return_as_link_text = caGetOption('returnAsLinkText', $pa_options, '');
     $vs_return_as_link_target = caGetOption('returnAsLinkTarget', $pa_options, '');
     $va_return_as_link_attributes = caGetOption('returnAsLinkAttributes', $pa_options, array(), array('castTo' => 'array'));
     $vb_return_all_locales = caGetOption('returnAllLocales', $pa_options, false, array('castTo' => 'bool'));
     $vs_delimiter = caGetOption('delimiter', $pa_options, '');
     $va_restrict_to_rel_types = caGetOption('restrictToRelationshipTypes', $pa_options, null);
     $va_filters = caGetOption('filters', $pa_options, array(), array('castTo' => 'array'));
     if ($vb_return_all_locales && !$vb_return_as_array) {
         $vb_return_as_array = true;
     }
     $va_return_values = null;
     // does get refer to an attribute?
     $va_tmp = explode('.', $ps_field);
     if (sizeof($va_tmp) > 1) {
         if ($va_tmp[0] != $this->tableName()) {
             $vs_access_chk_key = $ps_field;
         } else {
             $va_tmp2 = $va_tmp;
             array_shift($va_tmp2);
             $vs_access_chk_key = join(".", $va_tmp2);
         }
     } else {
         $vs_access_chk_key = $ps_field;
     }
     if ($va_tmp[sizeof($va_tmp) - 1] != 'access' && (!$this->hasField($va_tmp[sizeof($va_tmp) - 1]) || $this->getFieldInfo($va_tmp[sizeof($va_tmp) - 1], 'ALLOW_BUNDLE_ACCESS_CHECK'))) {
         // Always allow "access" value to be gotten otherwise none of the Pawtucket access checks will work.
         if (caGetBundleAccessLevel($this->tableName(), $vs_access_chk_key) == __CA_BUNDLE_ACCESS_NONE__) {
             return null;
         }
     }
     switch (sizeof($va_tmp)) {
         # -------------------------------------
         case 1:
             // table_name
             if ($t_instance = $this->_DATAMODEL->getInstanceByTableName($va_tmp[0], true)) {
                 $vs_pk = $t_instance->primaryKey();
                 $va_related_items = $this->getRelatedItems($va_tmp[0], $pa_options);
                 if (!is_array($va_related_items)) {
                     return null;
                 }
                 if (!$vs_template && !$vb_return_all_locales && !$vb_return_as_array) {
                     $vs_template = "^preferred_labels";
                 }
                 if ($vb_return_all_locales) {
                     $va_related_tmp = array();
                     foreach ($va_related_items as $vn_i => $va_related_item) {
                         $va_related_tmp[$vn_i][$va_related_item['locale_id']] = $va_related_item;
                     }
                     $va_related_items = $va_related_tmp;
                 } else {
                     if ($vs_template) {
                         $va_template_opts = $pa_options;
                         unset($va_template_opts['request']);
                         unset($va_template_opts['template']);
                         $va_template_opts['returnAsLink'] = false;
                         $va_template_opts['returnAsArray'] = true;
                         $va_template_opts['requireLinkTags'] = true;
                         $va_ids = array();
                         if (is_array($va_rel_items = $this->get($va_tmp[0], $va_template_opts))) {
                             foreach ($va_rel_items as $vn_rel_id => $va_rel_item) {
                                 $va_ids[] = $va_rel_item[$vs_pk];
                                 $va_template_opts['relationshipValues'][$va_rel_item[$vs_pk]][$va_rel_item['relation_id']]['relationship_typename'] = $va_rel_item['relationship_typename'];
                                 $va_template_opts['relationshipValues'][$va_rel_item[$vs_pk]][$va_rel_item['relation_id']]['relationship_type_id'] = $va_rel_item['relationship_type_id'];
                                 $va_template_opts['relationshipValues'][$va_rel_item[$vs_pk]][$va_rel_item['relation_id']]['label'] = $va_rel_item['label'];
                             }
                         } else {
                             $va_rel_items = array();
                         }
                         $va_text = caProcessTemplateForIDs($vs_template, $va_tmp[0], $va_ids, $va_template_opts);
                         if ($vb_return_as_link) {
                             $va_text = caCreateLinksFromText($va_text, $va_tmp[0], $va_ids, $vs_return_as_link_class, $vs_return_as_link_target);
                         }
                         if ($vb_return_as_array) {
                             $va_return_values = $va_text;
                         }
                         if (is_array($va_text)) {
                             return join($vs_delimiter, $va_text);
                         } else {
                             return null;
                         }
                     }
                 }
                 $va_return_values = $va_related_items;
             }
             break;
             # -------------------------------------
         # -------------------------------------
         case 2:
             // table_name.field_name || table_name.related
         // table_name.field_name || table_name.related
         case 3:
             // table_name.field_name.sub_element || table_name.related.field_name
         // table_name.field_name.sub_element || table_name.related.field_name
         case 4:
             // table_name.related.field_name.sub_element
             //
             // TODO: this code is compact, relatively simple and works but is slow since it
             // generates a lot more identical database queries than we'd like
             // We will need to add some notion of caching so that multiple calls to get()
             // for various fields in the same list of related items don't cause repeated queries
             //
             $vb_is_related = false;
             $vb_is_hierarchy = false;
             if ($va_tmp[1] === 'related') {
                 array_splice($va_tmp, 1, 1);
                 $vb_is_related = true;
             }
             if ($vb_is_related || $va_tmp[0] !== $this->tableName()) {
                 // must be related table
                 if (!($t_instance = $this->_DATAMODEL->getInstanceByTableName($va_tmp[0], true))) {
                     return null;
                 }
                 $vs_pk = $t_instance->primaryKey();
                 if ($vs_template && !$vb_return_all_locales) {
                     $va_template_opts = $pa_options;
                     unset($va_template_opts['request']);
                     unset($va_template_opts['template']);
                     $va_template_opts['returnAsLink'] = false;
                     $va_template_opts['returnAsArray'] = true;
                     $va_template_opts['requireLinkTags'] = true;
                     $va_ids = array();
                     if (is_array($va_rel_items = $this->get($va_tmp[0], $va_template_opts))) {
                         foreach ($va_rel_items as $vn_rel_id => $va_rel_item) {
                             $va_ids[] = $va_rel_item[$vs_pk];
                             $va_template_opts['relationshipValues'][$va_rel_item[$vs_pk]][$va_rel_item['relation_id']]['relationship_typename'] = $va_rel_item['relationship_typename'];
                         }
                     } else {
                         $va_rel_items = array();
                     }
                     $va_text = caProcessTemplateForIDs($vs_template, $va_tmp[0], $va_ids, $va_template_opts);
                     if ($vb_return_as_link) {
                         $va_text = caCreateLinksFromText($va_text, $va_tmp[0], $va_ids, $vs_return_as_link_class, $vs_return_as_link_target);
                     }
                     if ($vb_return_as_array) {
                         $va_return_values = $va_text;
                     }
                     return join($vs_delimiter, $va_text);
                 }
                 $va_related_items = $this->getRelatedItems($va_tmp[0], array_merge($pa_options, array('returnLabelsAsArray' => true)));
                 if (is_array($va_restrict_to_rel_types) && sizeof($va_restrict_to_rel_types)) {
                     require_once __CA_MODELS_DIR__ . '/ca_relationship_types.php';
                     $t_rel_types = new ca_relationship_types();
                     $va_restrict_to_rel_types = $t_rel_types->relationshipTypeListToIDs($t_rel_types->getRelationshipTypeTable($this->tableName(), $va_tmp[0]), $va_restrict_to_rel_types, array('includeChildren' => true));
                 }
                 $vb_field_is_specified = sizeof($va_tmp) == 2 && (!$vb_is_hierarchy && $va_tmp[1] != 'related') || sizeof($va_tmp) >= 3;
                 $va_ids = array();
                 $va_items = array();
                 if (is_array($va_related_items) && sizeof($va_related_items) > 0) {
                     foreach ($va_related_items as $vn_rel_id => $va_related_item) {
                         $va_ids[] = $va_related_item[$vs_pk];
                         if (is_array($va_restrict_to_rel_types) && !in_array($va_related_item['relationship_type_id'], $va_restrict_to_rel_types)) {
                             continue;
                         }
                         if ($va_tmp[1] == 'relationship_typename') {
                             $va_items[] = $va_related_item['relationship_typename'];
                             continue;
                         }
                         if ($va_tmp[1] == 'hierarchy') {
                             $vb_is_hierarchy = true;
                             if ($t_instance->load($va_related_item[$t_instance->primaryKey()])) {
                                 $va_items[] = $t_instance->get(join('.', $va_tmp), $pa_options);
                             }
                             continue;
                         }
                         // is field directly returned by getRelatedItems()?
                         if (isset($va_tmp[1]) && isset($va_related_item[$va_tmp[1]]) && $t_instance->hasField($va_tmp[1])) {
                             if ($vb_return_as_array) {
                                 if ($vb_return_all_locales) {
                                     // for return as locale-index array
                                     $va_items[$va_related_item['relation_id']][$va_related_item['locale_id']][] = $va_related_item[$va_tmp[1]];
                                 } else {
                                     // for return as simple array
                                     $va_items[] = $va_related_item[$va_tmp[1]];
                                 }
                             } else {
                                 // for return as string
                                 $va_items[] = $va_related_item[$va_tmp[1]];
                             }
                             continue;
                         }
                         // is field preferred labels?
                         if ($va_tmp[1] === 'preferred_labels') {
                             if (!isset($va_tmp[2])) {
                                 if ($vb_return_as_array || $vb_return_all_locales) {
                                     if ($vb_return_all_locales) {
                                         // for return as locale-index array
                                         $va_items[$va_related_item['relation_id']][] = $va_related_item['labels'];
                                     } else {
                                         // for return as simple array
                                         $va_item_list = caExtractValuesByUserLocale(array($va_related_item['labels']));
                                         foreach ($va_item_list as $vn_x => $va_item) {
                                             $va_items[] = $va_item[$t_instance->getLabelDisplayField()];
                                         }
                                     }
                                 } else {
                                     // for return as string
                                     $va_items[] = $va_related_item['label'][$t_instance->getLabelDisplayField()];
                                 }
                             } else {
                                 if ($vb_return_all_locales) {
                                     // for return as locale-index array
                                     foreach ($va_related_item['labels'] as $vn_locale_id => $va_label) {
                                         $va_items[$va_related_item['relation_id']][$vn_locale_id][] = $va_label[$va_tmp[2]];
                                     }
                                 } else {
                                     foreach (caExtractValuesByUserLocale(array($va_related_item['labels'])) as $vn_i => $va_label) {
                                         // for return as string or simple array
                                         $va_items[] = $va_label[$va_tmp[2]];
                                     }
                                 }
                             }
                             continue;
                         }
                         // TODO: add support for nonpreferred labels
                         // Get related attributes
                         if ($t_instance->load($va_related_item[$t_instance->primaryKey()])) {
                             if (isset($va_tmp[1])) {
                                 if ($vm_val = $t_instance->get(join(".", $va_tmp), $pa_options)) {
                                     if ($vb_return_as_link && !$vb_return_as_array && !$vb_return_all_locales) {
                                         $va_items[] = $vm_val;
                                     } else {
                                         $va_items[] = $vm_val;
                                         //break;
                                     }
                                 }
                             } else {
                                 $va_items[] = $this->get($va_tmp[0], $pa_options);
                             }
                         } else {
                             $va_items[] = null;
                         }
                     }
                 }
                 if ($vb_return_as_link && !$vb_return_all_locales) {
                     $va_items = caCreateLinksFromText($va_items, $va_tmp[0], $va_ids, $vs_return_as_link_class, $vs_return_as_link_target);
                 }
                 if ($vb_return_as_array) {
                     $va_return_values = $va_items;
                 } else {
                     return join($vs_delimiter, $va_items);
                 }
             }
             break;
             # -------------------------------------
     }
     if (!$va_return_values) {
         $va_return_values = parent::get($ps_field, $pa_options);
     }
     //
     // Perform filtering
     //
     if ($vb_return_as_array && sizeof($va_filters)) {
         $va_tmp = explode(".", $ps_field);
         if (sizeof($va_tmp) > 1) {
             array_pop($va_tmp);
         }
         if ($t_instance = $this->getAppDataModel()->getInstanceByTableName($va_tmp[0], true)) {
             $va_keepers = array();
             foreach ($va_filters as $vs_filter => $va_filter_vals) {
                 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?
                     if (!is_numeric($vs_filter_val) && (($t_element = $t_instance->_getElementInstance($vs_filter)) && $t_element->get('datatype') == 3)) {
                         $va_filter_vals[$vn_index] = caGetListItemID($t_element->get('list_id'), $vs_filter_val);
                     }
                 }
                 $va_filter_values = $this->get(join(".", $va_tmp) . ".{$vs_filter}", array('returnAsArray' => true));
                 if (!is_array($va_filter_values)) {
                     $va_filter_values = array();
                 }
                 foreach ($va_filter_values as $vn_id => $vm_filtered_val) {
                     if ((!isset($va_keepers[$vn_id]) || $va_keepers[$vn_id]) && in_array($vm_filtered_val, $va_filter_vals)) {
                         // any match for the element counts
                         $va_keepers[$vn_id] = true;
                     } else {
                         // if no match on any criteria kill it
                         $va_keepers[$vn_id] = false;
                     }
                 }
             }
             $va_filtered_vals = array();
             foreach ($va_keepers as $vn_id => $vb_include) {
                 if (!$vb_include) {
                     continue;
                 }
                 $va_filtered_vals[$vn_id] = $va_return_values[$vn_id];
             }
             return $va_filtered_vals;
         }
     }
     return $va_return_values;
 }
コード例 #4
0
 private function getModelInfoForType($ps_type)
 {
     $t_instance = $this->_getTableInstance($this->getTableName());
     $t_list = new ca_lists();
     $va_return = array();
     $vs_type_list_code = $t_instance->getTypeListCode();
     // type info
     $va_item = $t_list->getItemFromList($vs_type_list_code, $ps_type);
     $va_return["type_info"] = $va_item;
     $va_return["type_info"]["display_label"] = $t_list->getItemFromListForDisplay($vs_type_list_code, $ps_type);
     // applicable element codes and related info
     $va_elements = array();
     $va_codes = $t_instance->getApplicableElementCodes($va_item["item_id"]);
     $va_codes = array_flip($va_codes);
     foreach ($va_codes as $vs_code => $va_junk) {
         // subelements
         $t_element = $t_instance->_getElementInstance($vs_code);
         foreach ($t_element->getElementsInSet() as $va_element_in_set) {
             if ($va_element_in_set["datatype"] == 0) {
                 continue;
             }
             // don't include sub-containers
             $va_element_in_set["datatype"] = ca_metadata_elements::getAttributeNameForTypeCode($va_element_in_set["datatype"]);
             $va_elements[$vs_code]["elements_in_set"][$va_element_in_set["element_code"]] = $va_element_in_set;
         }
         // element label and description
         $va_label = $t_instance->getAttributeLabelAndDescription($vs_code);
         $va_elements[$vs_code]["name"] = $va_label["name"];
         if (isset($va_label["description"])) {
             $va_elements[$vs_code]["description"] = $va_label["description"];
         }
     }
     $va_return["elements"] = $va_elements;
     // possible relationships with "valid tables" (i.e. those that are accessible via services)
     $t_rel_types = new ca_relationship_types();
     foreach ($this->opa_valid_tables as $vs_table) {
         $vs_rel_table = $t_rel_types->getRelationshipTypeTable($this->getTableName(), $vs_table);
         $va_info = $t_rel_types->getRelationshipInfo($vs_rel_table);
         foreach ($va_info as $va_tmp) {
             $va_return["relationship_types"][$vs_table][$va_tmp["type_code"]] = $va_tmp;
         }
     }
     return $va_return;
 }