/**
  *
  */
 public function refine(&$pa_destination_data, $pa_group, $pa_item, $pa_source_data, $pa_options = null)
 {
     $o_log = isset($pa_options['log']) && is_object($pa_options['log']) ? $pa_options['log'] : null;
     // Set place hierarchy
     if ($vs_hierarchy = $pa_item['settings']['placeSplitter_placeHierarchy']) {
         $vn_hierarchy_id = caGetListItemID('place_hierarchies', $vs_hierarchy);
     } else {
         // Default to first place hierarchy
         $t_list = new ca_lists();
         $va_hierarchy_ids = $t_list->getItemsForList('place_hierarchies', array('idsOnly' => true));
         $vn_hierarchy_id = array_shift($va_hierarchy_ids);
     }
     if (!$vn_hierarchy_id) {
         if ($o_log) {
             $o_log->logError(_t('[placeSplitterRefinery] No place hierarchies are defined'));
         }
         return array();
     }
     $pa_options['hierarchyID'] = $vn_hierarchy_id;
     $t_place = new ca_places();
     if ($t_place->load(array('parent_id' => null, 'hierarchy_id' => $vn_hierarchy_id))) {
         $pa_options['defaultParentID'] = $t_place->getPrimaryKey();
     }
     return caGenericImportSplitter('placeSplitter', 'place', 'ca_places', $this, $pa_destination_data, $pa_group, $pa_item, $pa_source_data, $pa_options);
 }
 public function setUp()
 {
     // don't forget to call parent so that request is set up correctly
     parent::setUp();
     // search subject table
     $this->setPrimaryTable('ca_objects');
     /**
      * @see http://docs.collectiveaccess.org/wiki/Web_Service_API#Creating_new_records
      * @see https://gist.githubusercontent.com/skeidel/3871797/raw/item_request.json
      */
     $vn_test_vocab_item_id = caGetListItemID('test_vocab', 'test');
     $this->assertGreaterThan(0, $vn_test_vocab_item_id);
     $vn_image_id = $this->addTestRecord('ca_objects', array('intrinsic_fields' => array('type_id' => 'image'), 'preferred_labels' => array(array("locale" => "en_US", "name" => "Just an image")), 'related' => array('ca_list_items' => array(array('item_id' => $vn_test_vocab_item_id, 'type_id' => 'depicts')))));
     $this->assertGreaterThan(0, $vn_image_id);
     // search queries
     $this->setSearchQueries(array('Just an image' => 1, 'Foo' => 1, '"Foo"' => 1, 'Bar' => 1, '"Bar"' => 1, 'ca_list_item_labels.name_singular:"Foo"' => 1, 'ca_list_item_labels.name_singular:"Bar"' => 1, 'Baz' => 0, '"Baz"' => 0, 'ca_list_item_labels.name_singular:"Baz"' => 0));
 }
 /**
  * Returns list of items in the specified table related to the currently loaded row or rows specified in options.
  * 
  * @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:
  *
  *		[Options controlling rows for which data is returned]
  *			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 will be used. [Default is null]
  *			row_id = Primary key value to use when fetching related items. If omitted or set to a false value (null, false, 0) then the primary key value of the currently loaded row is used. [Default is currently loaded row]
  *			start = Zero-based index to begin return set at. [Default is 0]
  *			limit = Maximum number of related items to return. [Default is 1000]
  *			showDeleted = Return related items that have been deleted. [Default is false]
  *			primaryIDs = array of primary keys in related table to exclude from returned list of items. Array is keyed on table name for compatibility with the parameter as used in the caProcessTemplateForIDs() helper [Default is null - nothing is excluded].
  *			restrictToBundleValues = Restrict returned items to those with specified bundle values. Specify an associative array with keys set to bundle names and key values set to arrays of values to filter on (eg. [bundle_name1 => [value1, value2, ...]]). [Default is null]
  *			where = Restrict returned items to specified field values. The fields must be intrinsic and in the related table. This option can be useful when you want to efficiently fetch specific rows from a related table. Note that multiple fields/values are logically AND'ed together – all must match for a row to be returned - and that only equivalence is supported. [Default is null]			
  *			criteria = Restrict returned items using SQL criteria appended directly onto the query. Criteria is used as-is and must be compatible with the generated SQL query. [Default is null]
  *
  *		[Options controlling scope of data in return value]
  *			restrictToTypes = Restrict returned items to those of the specified types. An array of list item idnos and/or item_ids may be specified. [Default is null]
  *			restrictToRelationshipTypes =  Restrict returned items to those related using the specified relationship types. An array of relationship type idnos and/or type_ids may be specified. [Default is null]
  *			excludeTypes = Restrict returned items to those *not* of the specified types. An array of list item idnos and/or item_ids may be specified. [Default is null]
  *			excludeRelationshipTypes = Restrict returned items to those *not* related using the specified relationship types. An array of relationship type idnos and/or type_ids may be specified. [Default is null]
  *			restrictToType = Synonym for restrictToTypes. [Default is null]
  *			restrictToRelationshipType = Synonym for restrictToRelationshipTypes. [Default is null]
  *			excludeType = Synonym for excludeTypes. [Default is null]
  *			excludeRelationshipType = Synonym for excludeRelationshipTypes. [Default is null]
  *			restrictToLists = Restrict returned items to those that are in one or more specified lists. This option is only relevant when fetching related ca_list_items. An array of list list_codes or list_ids may be specified. [Default is null]
  * 			fields = array of fields (in table.fieldname format) to include in returned data. [Default is null]
  *			returnNonPreferredLabels = Return non-preferred labels in returned data. [Default is false]
  *			returnLabelsAsArray = Return all labels associated with row in an array, rather than as a text value in the current locale. [Default is false]
  *			dontReturnLabels = Don't include labels in returned data. [Default is false]
  *			idsOnly = Return one-dimensional array of related primary key values only. [Default is false]
  *
  *		[Options controlling format of data in return value]
  *			useLocaleCodes = Return locale values as codes (Ex. en_US) rather than numeric database-specific locale_ids. [Default is false]
  *			sort = Array list of bundles to sort returned values on. The sortable bundle specifiers are fields with or without tablename. Only those fields returned for the related tables (intrinsics, attributes and label fields) are sortable. [Default is null]
  *			sortDirection = Direction of sort. Use "asc" (ascending) or "desc" (descending). [Default is asc]
  *			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]
  *
  *		[Front-end access control]	
  *			checkAccess = Array of access values to filter returned values on. Available for any related table with an "access" field (ca_objects, ca_entities, etc.). If omitted no filtering is performed. [Default is null]
  *			user_id = Perform item level access control relative to specified user_id rather than currently logged in user. [Default is user_id for currently logged in user]
  *
  * @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 (($pa_options['restrictToTypes'] = caGetOption(array('restrictToTypes', 'restrict_to_types', 'restrictToType', 'restrict_to_type'), $pa_options, null)) && !is_array($pa_options['restrictToTypes'])) {
         $pa_options['restrictToTypes'] = array($pa_options['restrictToTypes']);
     }
     if (($pa_options['restrictToRelationshipTypes'] = caGetOption(array('restrictToRelationshipTypes', 'restrict_to_relationship_types', 'restrictToRelationshipType', 'restrict_to_relationship_type'), $pa_options, null)) && !is_array($pa_options['restrictToRelationshipTypes'])) {
         $pa_options['restrictToRelationshipTypes'] = array($pa_options['restrictToRelationshipTypes']);
     }
     if (($pa_options['excludeTypes'] = caGetOption(array('excludeTypes', 'exclude_types', 'excludeType', 'exclude_type'), $pa_options, null)) && !is_array($pa_options['excludeTypes'])) {
         $pa_options['excludeTypes'] = array($pa_options['excludeTypes']);
     }
     if (($pa_options['excludeRelationshipTypes'] = caGetOption(array('excludeRelationshipTypes', 'exclude_relationship_types', 'excludeRelationshipType', 'exclude_relationship_type'), $pa_options, null)) && !is_array($pa_options['excludeRelationshipTypes'])) {
         $pa_options['excludeRelationshipTypes'] = array($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['dontIncludeSubtypesInTypeRestriction'] = $pa_options['dont_include_subtypes_in_type_restriction'];
     }
     if (!isset($pa_options['returnNonPreferredLabels']) && (isset($pa_options['restrict_to_type']) && $pa_options['restrict_to_type'])) {
         $pa_options['returnNonPreferredLabels'] = $pa_options['restrict_to_type'];
     }
     if (!isset($pa_options['returnLabelsAsArray']) && (isset($pa_options['return_labels_as_array']) && $pa_options['return_labels_as_array'])) {
         $pa_options['returnLabelsAsArray'] = $pa_options['return_labels_as_array'];
     }
     if (!isset($pa_options['restrictToLists']) && (isset($pa_options['restrict_to_lists']) && $pa_options['restrict_to_lists'])) {
         $pa_options['restrictToLists'] = $pa_options['restrict_to_lists'];
     }
     $vb_group_fields = isset($pa_options['groupFields']) ? $pa_options['groupFields'] : false;
     $va_primary_ids = isset($pa_options['primaryIDs']) && is_array($pa_options['primaryIDs']) ? $pa_options['primaryIDs'] : null;
     $vb_show_current_only = isset($pa_options['showCurrentOnly']) ? $pa_options['showCurrentOnly'] : false;
     if (!isset($pa_options['useLocaleCodes']) && (isset($pa_options['returnLocaleCodes']) && $pa_options['returnLocaleCodes'])) {
         $pa_options['useLocaleCodes'] = $pa_options['returnLocaleCodes'];
     }
     $vb_use_locale_codes = isset($pa_options['useLocaleCodes']) ? $pa_options['useLocaleCodes'] : 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();
     $o_db = $this->getDb();
     $t_locale = $this->getLocaleInstance();
     $o_tep = $this->getTimeExpressionParser();
     $vb_uses_effective_dates = false;
     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['returnLabelsAsArray']) && $pa_options['returnLabelsAsArray'] ? 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();
     }
     $vb_is_combo_key_relation = false;
     // indicates relation is via table_num/row_id combination key
     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 = $this->isRelationship() ? $this : null;
             $t_rel_item = $this->getAppDatamodel()->getTableInstance($va_path[1]);
             $vs_key = $t_rel_item->primaryKey();
             break;
         default:
             // is this related with row_id/table_num combo?
             if (($t_rel_item = $this->getAppDatamodel()->getTableInstance($vs_related_table_name)) && $t_rel_item->hasField('table_num') && $t_rel_item->hasField('row_id')) {
                 $vs_key = $t_rel_item->primaryKey();
                 $vb_is_combo_key_relation = true;
                 $va_path = array($this->tableName(), $t_rel_item->tableName());
             } else {
                 // 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_tmp = $t_item_rel) || $t_rel_item->isRelationship() && ($t_tmp = $t_rel_item)) {
         //define table names
         $vs_linking_table = $t_tmp->tableName();
         $va_selects[] = "{$vs_related_table}." . $t_rel_item->primaryKey();
         // include dates in returned data
         if ($t_tmp->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_tmp->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['restrictToRelationshipTypes']) && $pa_options['restrictToRelationshipTypes']) {
             if (!is_array($pa_options['restrictToRelationshipTypes'])) {
                 $pa_options['restrictToRelationshipTypes'] = array($pa_options['restrictToRelationshipTypes']);
             }
             if (sizeof($pa_options['restrictToRelationshipTypes'])) {
                 $va_rel_types = array();
                 foreach ($pa_options['restrictToRelationshipTypes'] 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['excludeRelationshipTypes']) && $pa_options['excludeRelationshipTypes']) {
             if (!is_array($pa_options['excludeRelationshipTypes'])) {
                 $pa_options['excludeRelationshipTypes'] = array($pa_options['excludeRelationshipTypes']);
             }
             if (sizeof($pa_options['excludeRelationshipTypes'])) {
                 $va_rel_types = array();
                 foreach ($pa_options['excludeRelationshipTypes'] 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
     $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['excludeType']) && $pa_options['excludeType']) {
         if (!isset($pa_options['excludeTypes']) || !is_array($pa_options['excludeTypes'])) {
             $pa_options['excludeTypes'] = array();
         }
         $pa_options['excludeTypes'][] = $pa_options['excludeType'];
     }
     if (isset($pa_options['excludeTypes']) && is_array($pa_options['excludeTypes'])) {
         $va_type_ids = caMakeTypeIDList($vs_related_table, $pa_options['excludeTypes']);
         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 ' . $vs_related_table_name . '.' . $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[] = "{$vs_related_table}.{$vs_idno_fld}";
     }
     if ($vs_idno_sort_fld = $t_rel_item->getProperty('ID_NUMBERING_SORT_FIELD')) {
         $va_selects[] = "{$vs_related_table}.{$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") && (!isset($pa_options['dontReturnLabels']) || !$pa_options['dontReturnLabels'])) {
         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['returnNonPreferredLabels']) || !$pa_options['returnNonPreferredLabels'])) {
                 $va_wheres[] = "(" . $vs_label_table_name . '.is_preferred = 1)';
             }
         }
     }
     if ($vb_show_current_only && $t_item_rel && $t_item_rel->hasField('source_info') && $t_item_rel->tableName() == 'ca_movements_x_objects') {
         // TODO: table check is temporary hack while we get "current" support into non-movement relationships
         $va_wheres[] = '(' . $t_item_rel->tableName() . '.source_info = \'current\')';
     }
     // 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[] = "({$vs_related_table}.access IN (" . join(',', $pa_options['checkAccess']) . "))";
     }
     if ((!isset($pa_options['showDeleted']) || !$pa_options['showDeleted']) && $t_rel_item->hasField('deleted')) {
         $va_wheres[] = "({$vs_related_table}.deleted = 0)";
     }
     if (($va_criteria = isset($pa_options['criteria']) ? $pa_options['criteria'] : null) && is_array($va_criteria) && sizeof($va_criteria)) {
         $va_wheres[] = "(" . join(" AND ", $va_criteria) . ")";
     }
     if ($vb_self_relationship) {
         //
         // START - traverse 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 {$vs_related_table}.{$vs_sort}";
                     $vs_sort_fld = $vs_sort;
                     $va_selects[] = "{$vs_related_table}.{$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}";
             $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;
                 }
                 if (is_array($va_primary_ids) && is_array($va_primary_ids[$vs_related_table])) {
                     if (in_array($qr_res->get($vs_key), $va_primary_ids[$vs_related_table])) {
                         continue;
                     }
                 }
                 $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];
                 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 ($vb_use_locale_codes) {
                     $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 ($vb_group_fields) {
                     $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 - traverse self relation
         //
     } else {
         if (method_exists($this, 'isSelfRelationship') && $this->isSelfRelationship()) {
             //
             // START - from self relation itself (Eg. get related ca_objects from ca_objects_x_objects); in this case there are two possible paths (keys) to check, "left" and "right"
             //
             $va_wheres[] = "(" . $this->tableName() . '.' . $this->primaryKey() . " IN (" . join(",", $va_row_ids) . "))";
             $vs_cur_table = array_shift($va_path);
             $vs_rel_table = array_shift($va_path);
             $va_rel_info = $this->getAppDatamodel()->getRelationships($vs_cur_table, $vs_rel_table);
             $va_rels = array();
             foreach ($va_rel_info[$vs_cur_table][$vs_rel_table] as $vn_i => $va_rel) {
                 $va_joins = array('INNER JOIN ' . $vs_rel_table . ' ON ' . $vs_cur_table . '.' . $va_rel[0] . ' = ' . $vs_rel_table . '.' . $va_rel[1] . "\n");
                 $vs_base_table = $vs_rel_table;
                 foreach ($va_path as $vs_join_table) {
                     $va_label_rel_info = $this->getAppDatamodel()->getRelationships($vs_base_table, $vs_join_table);
                     $va_joins[] = 'INNER JOIN ' . $vs_join_table . ' ON ' . $vs_base_table . '.' . $va_label_rel_info[$vs_base_table][$vs_join_table][0][0] . ' = ' . $vs_join_table . '.' . $va_label_rel_info[$vs_base_table][$vs_join_table][0][1] . "\n";
                     $vs_base_table = $vs_join_table;
                 }
                 $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';
                     $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 {$vs_related_table}.{$vs_sort}";
                         $va_selects[] = "{$vs_related_table}.{$vs_sort}";
                     }
                 }
                 $vs_sql = "\n\t\t\t\t\tSELECT DISTINCT " . join(', ', $va_selects) . "\n\t\t\t\t\tFROM " . $this->tableName() . "\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 ', $va_wheres) . "\n\t\t\t\t\t{$vs_order_by}\n\t\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';
                 }
                 $vn_c = 0;
                 if ($vn_start > 0) {
                     $qr_res->seek($vn_start);
                 }
                 while ($qr_res->nextRow()) {
                     if ($vn_c >= $vn_limit) {
                         break;
                     }
                     if (is_array($va_primary_ids) && is_array($va_primary_ids[$vs_related_table])) {
                         if (in_array($qr_res->get($vs_key), $va_primary_ids[$vs_related_table])) {
                             continue;
                         }
                     }
                     if (isset($pa_options['idsOnly']) && $pa_options['idsOnly']) {
                         $va_rels[] = $qr_res->get($t_rel_item->primaryKey());
                         continue;
                     }
                     $va_row = $qr_res->getRow();
                     $vs_v = $va_row['row_id'] . '/' . $va_row[$vs_key];
                     $vs_display_label = $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 ($vb_use_locale_codes) {
                         $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 ($vb_group_fields) {
                         $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['idsOnly']) || !$pa_options['idsOnly']) {
                     // 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 - from self relation itself
             //
         } 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['restrictToLists'])) {
                 $va_list_ids = array();
                 foreach ($pa_options['restrictToLists'] 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) . "))";
                 }
             }
             if ($vb_is_combo_key_relation) {
                 $va_joins = array("INNER JOIN {$vs_related_table_name} ON {$vs_related_table_name}.row_id = " . $this->primaryKey(true) . " AND {$vs_related_table_name}.table_num = " . $this->tableNum());
             } else {
                 foreach ($va_path as $vs_join_table) {
                     $va_rel_info = $this->getAppDatamodel()->getRelationships($vs_cur_table, $vs_join_table);
                     $vs_join = 'INNER JOIN ' . $vs_join_table . ' ON ';
                     $va_tmp = array();
                     foreach ($va_rel_info[$vs_cur_table][$vs_join_table] as $vn_i => $va_rel) {
                         $va_tmp[] = $vs_cur_table . "." . $va_rel_info[$vs_cur_table][$vs_join_table][$vn_i][0] . ' = ' . $vs_join_table . '.' . $va_rel_info[$vs_cur_table][$vs_join_table][$vn_i][1] . "\n";
                     }
                     $va_joins[] = $vs_join . join(' OR ', $va_tmp);
                     $vs_cur_table = $vs_join_table;
                 }
             }
             // If we're getting ca_set_items, we have to rename the intrinsic row_id field because the pk is named row_id below. Hence, this hack.
             if ($vs_related_table_name == 'ca_set_items') {
                 $va_selects[] = 'ca_set_items.row_id AS record_id';
             }
             $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';
                 $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 {$vs_related_table}.{$vs_sort}";
                     $va_selects[] = "{$vs_related_table}.{$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";
             $qr_res = $o_db->query($vs_sql);
             if ($vb_uses_relationship_types) {
                 $va_rel_types = $t_rel->getRelationshipInfo($t_tmp->tableName());
                 if (method_exists($t_tmp, 'getLeftTableName')) {
                     $vs_left_table = $t_tmp->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 (is_array($va_primary_ids) && is_array($va_primary_ids[$vs_related_table])) {
                     if (in_array($qr_res->get($vs_key), $va_primary_ids[$vs_related_table])) {
                         continue;
                     }
                 }
                 if (isset($pa_options['idsOnly']) && $pa_options['idsOnly']) {
                     $va_rels[] = $qr_res->get($t_rel_item->primaryKey());
                     continue;
                 }
                 $va_row = $qr_res->getRow();
                 $vs_v = sizeof($va_path) <= 2 ? $va_row['row_id'] . '/' . $va_row[$vs_key] : $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 ($vb_use_locale_codes) {
                     $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 ($vb_group_fields) {
                     $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['idsOnly']) || !$pa_options['idsOnly']) {
                 // 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 = isset($pa_options['restrictToBundleValues']) ? $pa_options['restrictToBundleValues'] : null;
     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;
 }
示例#4
0
 /**
  * Rewrite browse config settings as needed before starting actual processing of browse
  */
 private function _processBrowseSettings()
 {
     $va_revised_facets = array();
     foreach ($this->opa_browse_settings['facets'] as $vs_facet_name => $va_facet_info) {
         // generate_facets_for_types config directive triggers auto-generation of facet config for each type of an authority item
         // it's typically employed to provide browsing of occurrences where the various types are unrelated
         // you can also use this on other authorities to provide a finer-grained browse without having to know the type hierarchy ahead of time
         if ($va_facet_info['type'] === 'authority' && isset($va_facet_info['generate_facets_for_types']) && $va_facet_info['generate_facets_for_types']) {
             // get types for authority
             $t_table = $this->opo_datamodel->getInstanceByTableName($va_facet_info['table'], true);
             $va_type_list = $t_table->getTypeList();
             // auto-generate facets
             foreach ($va_type_list as $vn_type_id => $va_type_info) {
                 if ($va_type_info['is_enabled']) {
                     $va_facet_info = array_merge($va_facet_info, array('label_singular' => $va_type_info['name_singular'], 'label_singular_with_indefinite_article' => _t('a') . ' ' . $va_type_info['name_singular'], 'label_plural' => $va_type_info['name_plural'], 'restrict_to_types' => array($va_type_info['item_id'])));
                     $va_revised_facets[$vs_facet_name . '_' . $vn_type_id] = $va_facet_info;
                 }
             }
         } else {
             $va_revised_facets[$vs_facet_name] = $va_facet_info;
         }
     }
     // rewrite single_value settings for attribute and fieldList facets
     foreach ($va_revised_facets as $vs_facet => $va_facet_info) {
         if (!(isset($va_facet_info['single_value']) && strlen($va_facet_info['single_value']))) {
             continue;
         }
         switch ($va_facet_info['type']) {
             case 'attribute':
                 $t_element = new ca_metadata_elements();
                 if ($t_element->load(array('element_code' => $va_facet_info['element_code']))) {
                     if ($t_element->get('datatype') == __CA_ATTRIBUTE_VALUE_LIST__ && ($vn_list_id = $t_element->get('list_id'))) {
                         if ($vn_item_id = caGetListItemID($vn_list_id, $va_facet_info['single_value'])) {
                             $va_revised_facets[$vs_facet]['single_value'] = $vn_item_id;
                         }
                     }
                 }
                 break;
             case 'fieldList':
                 $t_instance = $this->opo_datamodel->getInstanceByTableName($this->ops_browse_table_name, true);
                 if ($vn_item_id = caGetListItemID($t_instance->getFieldInfo($va_facet_info['field'], 'LIST_CODE'), $va_facet_info['single_value'])) {
                     $va_revised_facets[$vs_facet]['single_value'] = $vn_item_id;
                 }
                 break;
         }
     }
     $this->opa_browse_settings['facets'] = $va_revised_facets;
 }
//print caBusyIndicatorIcon($this->request).' '.addslashes(_t('Loading...'));
$va_rel_ids = $t_item->get('ca_objects_x_entities.relation_id', array('returnAsArray' => true));
$qr_rels = caMakeSearchResult('ca_objects_x_entities', $va_rel_ids, array('sort' => 'ca_objects_x_entities.date_out'));
// set all of the page object_ids
$va_page_ids = array();
while ($qr_rels->nextHit()) {
    $va_page_ids[] = $qr_rels->get("ca_objects_x_entities.see_original_link", array('idsOnly' => 1));
}
$qr_pages = caMakeSearchResult('ca_objects', $va_page_ids);
$va_parents = array();
while ($qr_pages->nextHit()) {
    $va_parents[$qr_pages->get('ca_objects.object_id')] = $qr_pages->get('ca_objects.parent.preferred_labels.name');
}
$qr_rels->seek(0);
// reset the result to the beginning so we can run through it again
$vn_page_type_id = caGetListItemID('object_types', 'page');
$vn_i = 0;
while ($qr_rels->nextHit()) {
    if ($qr_rels->get('ca_objects.type_id') == $vn_page_type_id) {
        continue;
    }
    print "<div class='row ledgerRow'>";
    print "<div class='col-xs-3 col-sm-3 col-md-3 col-lg-3' id='book" . $vn_i . "'>";
    if ($qr_rels->get("ca_objects.parent.preferred_labels")) {
        $va_label_trunk = explode(':', $qr_rels->get("ca_objects.parent.preferred_labels"));
        print caNavLink($this->request, $va_label_trunk[0], '', '', 'Detail', 'objects/' . $qr_rels->get("ca_objects.parent.object_id"));
    } else {
        $va_label_trunk = explode(':', $qr_rels->get("ca_objects.preferred_labels"));
        print caNavLink($this->request, $va_label_trunk[0], '', '', 'Detail', 'objects/' . $qr_rels->get("ca_objects.object_id"));
    }
    $va_book_info = array();
示例#6
0
 /**
  * @param array $pa_config
  * @param RequestHTTP $po_request
  * @return array
  * @throws Exception
  */
 private static function runSearchEndpoint($pa_config, $po_request)
 {
     $o_dm = Datamodel::load();
     // load blank instance
     $t_instance = $o_dm->getInstance($pa_config['table']);
     if (!$t_instance instanceof BundlableLabelableBaseModelWithAttributes) {
         throw new Exception('invalid table');
     }
     if (!($ps_q = $po_request->getParameter('q', pString))) {
         throw new Exception('No query specified');
     }
     $o_search = caGetSearchInstance($pa_config['table']);
     // restrictToTypes
     if ($pa_config['restrictToTypes'] && is_array($pa_config['restrictToTypes']) && sizeof($pa_config['restrictToTypes']) > 0) {
         $va_type_filter = array();
         foreach ($pa_config['restrictToTypes'] as $vs_type_code) {
             $va_type_filter[] = caGetListItemID($t_instance->getTypeListCode(), $vs_type_code);
         }
         $o_search->addResultFilter($t_instance->tableName() . '.type_id', 'IN', join(",", $va_type_filter));
     }
     $o_res = $o_search->search($ps_q, array('sort' => $po_request->getParameter('sort', pString), 'sortDirection' => $po_request->getParameter('sortDirection', pString), 'start' => $po_request->getParameter('start', pInteger), 'limit' => $po_request->getParameter('limit', pInteger), 'checkAccess' => $pa_config['checkAccess']));
     $va_return = array();
     while ($o_res->nextHit()) {
         $va_hit = array();
         foreach ($pa_config['content'] as $vs_key => $vs_template) {
             $va_hit[self::sanitizeKey($vs_key)] = $o_res->getWithTemplate($vs_template);
         }
         $va_return[$o_res->get($t_instance->primaryKey(true))] = $va_hit;
     }
     return $va_return;
 }
示例#7
0
 /**
  * Returns a value from the query result. This can be a single value if it is a field in the subject table (eg. objects table in an objects search), or
  * perhaps multiple related values (eg. related entities in an objects search). 
  *
  * You can fetch the values attached to a subject using the bundle specification, generally in the format <subject_table_name>.<element_code> (ex. ca_objects.date_created)
  * If the bundle is a container then you can fetch a specific value using the format <subject_table_name>.<attribute_element_code>.<value_element_code>
  * For example, to get the "date_value" value out of a "date" container attached to a ca_objects row, get() would be called with the field parameter set to ca_objects.date.date_value
  *
  * By default get() returns a string for display in the current locale. You can control the formatting of the output using various options described below including "template" (format output using a displayt template),
  * "makeLink" (convert references to records into clickable links) and "delimiter" (specify text to place between multiple values)
  *
  * When the "returnAsArray" option is set get() will return a numerically indexed array list of values. This array will always be one-dimensional with a sequence of display values.
  *
  * You can force values for all available locales to be included in the returned string or array list using the "returnAllLocales" option.
  * 
  * CollectiveAccess stores related, repeating and multilingual data in a fairly complex series of nested structures. get() is intended to faciliate output of data so most of its options are geared towards
  * flattening of data for easy of formatting and display, with commensurate loss of internal structre. Set the "returnWithStructure" option to obtain the "raw" data with all of its internal structure intact. The
  * returned value will be a multidimensional array tailored to the type of data being returned. Typically this array will be indexed first by the id of the record to which the returned data is attached, then
  * by locale_id or code (if "returnAllLocales" is set), then the id specific to the data item (Eg. internal attribute_id for metadata, label_id for labels, Etc.), and finally an array with keys set to data element names
  * and associated values.
  *
  * Return values can be modified using the following options:
  *
  *		[Options controlling type of return value]
  *			returnAsArray = return values in a one-dimensional, numerically indexed array. If not not a string is always returned. [Default is false]
  *			returnWithStructure = return values in a multi-dimensional array mirroring the internal storage structure of CollectiveAccess. [Default is false]
  *
  *		[Options controlling scope of data in return value]
  *			returnAllLocales = Return values from all available locales, rather than just the most appropriate locale for the current user. For string and array return values, returnAllLocales will result in inclusion of additional values. For returnWithStructure, additional entries keys on locale_id or code will be added.  [Default is false]
  *			useLocaleCodes =  For returnWithStructure locale codes (ex. en_US) will be used rather than numeric locale_ids. [Default is false]
  * 			restrictToTypes = For bundles referencing data in related tables (ex. calling ca_entities.idno from a ca_objects result) will restrict returned items to those of the specified types. An array of list item idnos and/or item_ids may be specified. [Default is null]
  *			restrictToRelationshipTypes =  For bundles referencing data in related tables (ex. calling ca_entities.idno from a ca_objects result) will restrict returned items to those related using the specified relationship types. An array of relationship type idnos and/or type_ids may be specified. [Default is null]
  *			excludeTypes = For bundles referencing data in related tables (ex. calling ca_entities.idno from a ca_objects result) will restrict returned items to those *not* of the specified types. An array of list item idnos and/or item_ids may be specified. [Default is null]
  *			excludeRelationshipTypes = For bundles referencing data in related tables (ex. calling ca_entities.idno from a ca_objects result) will restrict returned items to those *not* related using the specified relationship types. An array of relationship type idnos and/or type_ids may be specified. [Default is null]
  *			restrictToType = Synonym for restrictToTypes. [Default is null]
  *			restrictToRelationshipType = Synonym for restrictToRelationshipTypes. [Default is null]
  *			excludeType = Synonym for excludeTypes. [Default is null]
  *			excludeRelationshipType = Synonym for excludeRelationshipTypes. [Default is null]
  *			filters = Array list of elements to filter returned values on. The element must be part of the container being fetched from. For example, when fetching a value from a container element (ex. 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 (ex. "date_type" => "copyright"). Pass only the name of the subelement, not the full path that includes the table and container element. You may 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 or returnWithStructure are set. [Default is null]
  *			assumeDisplayField = For returnWithStructure, return display field for ambiguous preferred label specifiers (ex. ca_entities.preferred_labels => ca_entities.preferred_labels.displayname). If set to false an array with all label fields is returned. [Default is true]
  *			returnURL = When fetching intrinsic value of type FT_MEDIA return URL to media rather than HTML tag. [Default is false]
  *			returnPath = When fetching intrinsic value of type FT_MEDIA return path to media rather than HTML tag. [Default is false] 
  *			unserialize = When fetching intrinsic value of type FT_VARS (serialized variables) return unserialized value. [Default is false]
  *			
  *		[Formatting options for strings and arrays]
  *			template = Display template use when formatting return values. @see http://docs.collectiveaccess.org/wiki/Display_Templates. [Default is null]
  *			delimiter = Characters to place in between repeating values when returning a string
  *			makeLink = Return value as a link to the relevant editor (Providence) or detail (Pawtucket) when bundle references data in a related table; return value as HTML link when value is URL type. [Default is false]
  *			returnAsLink = Synonym for makeLink. [Default is false]
  *			convertCodesToDisplayText = Convert list item_ids text in the user's preferred locale for display. [Default is false]
  *			convertCodesToIdno = Convert list item_ids to idno's (ca_list_items.idno). If convertCodesToDisplayText is also set then it will take precedence. [Default is false]
  *			output = Convert list item_ids to display text in user's preferred locale ("text") or idno ("idno"). This is an easier to type alternative to the convertCodesToDisplayText and convertCodesToIdno options. [Default is null]
  *			sort = Array list of bundles to sort returned values on. Currently sort is only supported when getting related values via simple related <table_name> and <table_name>.related bundle specifiers. Eg. from a ca_objects results you can sort when fetching 'ca_entities', 'ca_entities.related', 'ca_objects.related', etc.. The sortable bundle specifiers are fields with or without tablename. Only those fields returned for the related tables (intrinsics and label fields) are sortable. You cannot currenty sort on attributes. [Default is null]
  *
  *		[Formatting options for hierarchies]
  *			maxLevelsFromTop = Restrict the number of levels returned to the top-most beginning with the root. [Default is null]
  *			maxLevelsFromBottom = Restrict the number of levels returned to the bottom-most starting with the lowest leaf node. [Default is null]
  *			maxLevels = synonym for maxLevelsFromBottom. [Default is null]
  *			hierarchyDirection = Order in which to return hierarchical levels. Set to either "asc" or "desc". "Asc"ending returns hierarchy beginning with the root; "desc"ending begins with the child furthest from the root. [Default is asc]
  *			allDescendants = Return all items from the full depth of the hierarchy when fetching children. By default only immediate children are returned. [Default is false]
  *
  *		[Front-end access control]		
  *			checkAccess = Array of access values to filter returned values on. Available for any table with an "access" field (ca_objects, ca_entities, etc.). If omitted no filtering is performed. [Default is null]
  *
  *
  *	@param string $ps_field 
  *	@param array $pa_options Options as described above
  * 	@return mixed String or array
  */
 public function get($ps_field, $pa_options = null)
 {
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     $vb_return_as_array = isset($pa_options['returnAsArray']) ? (bool) $pa_options['returnAsArray'] : false;
     $va_filters = is_array($pa_options['filters']) ? $pa_options['filters'] : array();
     // Add table name to field specs that lack it
     if (strpos($ps_field, '.') === false && !$this->opo_datamodel->tableExists($ps_field)) {
         $va_tmp = array($this->ops_table_name, $ps_field);
         $ps_field = $this->ops_table_name . ".{$ps_field}";
     }
     if (isset($pa_options['template']) && $pa_options['template']) {
         return $this->getWithTemplate($pa_options['template'], $pa_options);
     }
     $vm_val = self::_get($ps_field, $pa_options);
     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 = SearchResult::$s_instance_cache[$va_tmp[0]])) {
             $t_instance = SearchResult::$s_instance_cache[$va_tmp[0]] = $this->opo_datamodel->getInstanceByTableName($va_tmp[0], true);
         }
         if ($t_instance) {
             $va_keepers = array();
             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?
                     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, 'alwaysReturnItemID' => true));
                 if (is_array($va_filter_values)) {
                     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] = $vm_val[$vn_id];
             }
             return $va_filtered_vals;
         }
     }
     return $vm_val;
 }
示例#8
0
/**
 * Converts the given list of list idnos or item_ids into a list of numeric item_ids
 *
 * @param mixed $pm_list List code or list_id
 * @param array $pa_list_items List of item idnos and/or item_ids 
 * @param array $pa_options Options include:
 *		transaction = transaction to execute queries within. [Default=null]
 *
 * @return array List of numeric item_ids
 */
function caMakeListItemIDList($pm_list, $pa_list_items, $pa_options = null)
{
    if (!($vn_list_id = caGetListID($pm_list))) {
        return array();
    }
    $t_item = new ca_list_items();
    if ($o_trans = caGetOption('transaction', $pa_options, null)) {
        $t_item->setTransaction($o_trans);
    }
    $va_ids = array();
    foreach ($pa_list_items as $vm_item) {
        if (is_numeric($vm_item) && (int) $vm_item > 0) {
            $va_ids[(int) $vm_item] = true;
        } else {
            if ($vn_id = caGetListItemID($vn_list_id, $vm_item)) {
                $va_ids[(int) $vn_id] = true;
            }
        }
    }
    return array_keys($va_ids);
}
 protected function search($pa_bundles = null)
 {
     $va_return = parent::search($pa_bundles);
     if ($this->getTableName() == 'ca_entities' && is_array($va_return['results']) && sizeof($va_return['results']) > 0) {
         $o_db = new Db();
         $t_element = new ca_metadata_elements();
         $t_element->load(array('element_code' => 'is_index_display'));
         $vn_element_id = $t_element->getPrimaryKey();
         if (!$vn_element_id) {
             return $va_return;
         }
         $vn_yes_id = caGetListItemID('yn', 'yes');
         foreach ($va_return['results'] as &$va_result) {
             $vn_entity_id = $va_result['entity_id'];
             $qr_objects = $o_db->query("\n\t\t\t\t\tSELECT DISTINCT ca_objects.object_id FROM ca_entities, ca_objects_x_entities, ca_objects, ca_attributes, ca_attribute_values\n\t\t\t\t\tWHERE ca_entities.entity_id = ca_objects_x_entities.entity_id\n\t\t\t\t\tAND ca_attributes.row_id = ca_objects.object_id\n\t\t\t\t\tAND ca_attribute_values.attribute_id = ca_attributes.attribute_id\n\t\t\t\t\tAND ca_objects_x_entities.object_id = ca_objects.object_id\n\t\t\t\t\tAND ca_attribute_values.element_id = ?\n\t\t\t\t\tAND ca_entities.entity_id = ?\n\t\t\t\t\tAND ca_attribute_values.item_id = ?\n\t\t\t\t\tAND ca_objects.deleted = 0\n\t\t\t\t", $vn_element_id, $vn_entity_id, $vn_yes_id);
             while ($qr_objects->nextRow()) {
                 $va_object_info = array();
                 $vn_object_id = $qr_objects->get('ca_objects.object_id');
                 if (MemoryCache::contains($vn_object_id, 'AboutDrawingServices')) {
                     $va_object_info = MemoryCache::fetch($vn_object_id, 'AboutDrawingServices');
                 } else {
                     $va_object_info['object_id'] = $vn_object_id;
                     $qr_labels = $o_db->query("\n\t\t\t\t\t\t\tSELECT ca_object_labels.* FROM ca_object_labels, ca_objects\n\t\t\t\t\t\t\tWHERE ca_object_labels.object_id = ca_objects.object_id\n\t\t\t\t\t\t\tAND ca_objects.object_id = ?\n\t\t\t\t\t\t", $vn_object_id);
                     $vs_label = '';
                     while ($qr_labels->nextRow()) {
                         $va_object_info['labels'][] = $qr_labels->getRow();
                         $vs_label = $qr_labels->get('name');
                         // keep the last label around
                     }
                     $va_object_info['label'] = $vs_label;
                     $qr_reps = $o_db->query("\n\t\t\t\t\t\t\tSELECT ca_object_representations.* FROM ca_object_representations, ca_objects_x_object_representations, ca_objects\n\t\t\t\t\t\t\tWHERE ca_object_representations.representation_id = ca_objects_x_object_representations.representation_id\n\t\t\t\t\t\t\tAND ca_objects_x_object_representations.object_id = ca_objects.object_id\n\t\t\t\t\t\t\tAND ca_objects.object_id = ?\n\t\t\t\t\t\t\tAND ca_objects.deleted = 0 AND ca_object_representations.deleted = 0\n\t\t\t\t\t\t", $vn_object_id);
                     while ($qr_reps->nextRow()) {
                         $va_object_info['representations'][] = array('representation_id' => $qr_reps->get('representation_id'), 'icon' => $qr_reps->getMediaUrl('media', 'icon'), 'preview170' => $qr_reps->getMediaUrl('media', 'preview170'), 'medium' => $qr_reps->getMediaUrl('media', 'medium'), 'original' => $qr_reps->getMediaUrl('media', 'original'));
                     }
                     MemoryCache::save($vn_object_id, $va_object_info, 'AboutDrawingServices');
                 }
                 $va_result['ca_objects'][] = $va_object_info;
             }
             /* the old&simple, but very slow code
             				$t_entity = new ca_entities($va_result['entity_id']);
             				$va_objects = $t_entity->getRelatedItems('ca_objects');
             
             				foreach($va_objects as $va_object) {
             					$t_object = new ca_objects($va_object['object_id']);
             					$va_reps = $t_object->getRepresentations(array('icon', 'preview170', 'medium', 'original'));
             					$va_representation_info = array();
             					foreach($va_reps as $va_rep) {
             						$va_representation_info[] = array(
             							'representation_id' => $va_rep['representation_id'],
             							'urls' => $va_rep['urls'],
             						);
             					}
             
             					$va_object_info = array();
             					$va_object_info['object_id'] = $va_object['object_id'];
             					$va_object_info['labels'] = $va_object['labels'];
             					$va_object_info['label'] = $va_object['label'];
             					$va_object_info['representations'] = $va_representation_info;
             
             					$va_result['ca_objects'][] = $va_object_info;
             				}*/
         }
     }
     return $va_return;
 }
示例#10
0
 /**
  * @param mixed $ps_value
  * @param array $pa_element_info
  * @param array $pa_options Options are:
  *		alwaysTreatValueAsIdno = Always try to convert $ps_value to a list idno value, even if it is numeric
  *		matchOn = 
  *
  * @return array
  */
 public function parseValue($ps_value, $pa_element_info, $pa_options = null)
 {
     $vb_treat_value_as_idno = caGetOption('alwaysTreatValueAsIdno', $pa_options, false);
     $va_match_on = caGetOption('matchOn', $pa_options, null);
     if ($va_match_on && !is_array($va_match_on)) {
         $va_match_on = array($va_match_on);
     }
     if (!is_array($va_match_on) && $vb_treat_value_as_idno) {
         $va_match_on = array('idno', 'item_id');
     }
     if ((!is_array($va_match_on) || !sizeof($va_match_on)) && preg_match('![^\\d]+!', $ps_value)) {
         $va_match_on = array('idno', 'item_id');
     }
     if ($vb_treat_value_as_idno && !in_array('idno', $va_match_on)) {
         array_push($va_match_on, 'idno');
     }
     if (!is_array($va_match_on) || !sizeof($va_match_on)) {
         $va_match_on = array('item_id');
     }
     $o_trans = caGetOption('transaction', $pa_options, null);
     $vb_require_value = is_null($pa_element_info['settings']['requireValue']) ? false : (bool) $pa_element_info['settings']['requireValue'];
     $ps_orig_value = $ps_value;
     $vn_id = null;
     $t_item = new ca_list_items();
     if ($o_trans) {
         $t_item->setTransaction($o_trans);
     }
     foreach ($va_match_on as $vs_match_on) {
         switch ($vs_match_on) {
             case 'idno':
                 // try to convert idno to item_id
                 if ($vn_id = caGetListItemID($pa_element_info['list_id'], $ps_value, $pa_options)) {
                     break 2;
                 }
                 break;
             case 'label':
             case 'labels':
                 // try to convert label to item_id
                 if ($vn_id = caGetListItemIDForLabel($pa_element_info['list_id'], $ps_value, $pa_options)) {
                     break 2;
                 }
                 break;
             case 'item_id':
             default:
                 if ($vn_id = ca_list_items::find(array('item_id' => (int) $ps_value, 'list_id' => $pa_element_info['list_id']), array('returnAs' => 'firstId'))) {
                     break 2;
                     //} else {
                     //$this->postError(1970, _t('Value with item_id %1 does not exist in list %2', $ps_value, $pa_element_info['list_id']), 'ListAttributeValue->parseValue()');
                 }
                 break;
         }
     }
     if (!$vb_require_value && !$vn_id) {
         return array('value_longtext1' => null, 'item_id' => null);
     } elseif ($vb_require_value && !$vn_id && !strlen($ps_value)) {
         $this->postError(1970, _t('Value for %1 [%2] cannot be blank', $pa_element_info['displayLabel'], $pa_element_info['element_code']), 'ListAttributeValue->parseValue()');
         return false;
     } elseif ($vb_require_value && !$vn_id) {
         $this->postError(1970, _t('Value %3 for %1 [%2] is invalid', $pa_element_info['displayLabel'], $pa_element_info['element_code'], $ps_value), 'ListAttributeValue->parseValue()');
         return false;
     }
     return array('value_longtext1' => (int) $vn_id, 'item_id' => (int) $vn_id);
 }
示例#11
0
 /**
  * Returns a value from the query result. This can be a single value if it is a field in the subject table (eg. objects table in an objects search), or
  * perhaps multiple related values (eg. related entities in an objects search). 
  *
  * You can fetch the values attached to a subject using the bundle specification, generally in the format <subject_table_name>.<element_code> (ex. ca_objects.date_created)
  * If the bundle is a container then you can fetch a specific value using the format <subject_table_name>.<attribute_element_code>.<value_element_code>
  * For example, to get the "date_value" value out of a "date" container attached to a ca_objects row, get() would be called with the field parameter set to ca_objects.date.date_value
  *
  * By default get() returns a string for display in the current locale. You can control the formatting of the output using various options described below including "template" (format output using a displayt template),
  * "makeLink" (convert references to records into clickable links) and "delimiter" (specify text to place between multiple values)
  *
  * When the "returnAsArray" option is set get() will return a numerically indexed array list of values. This array will always be one-dimensional with a sequence of display values.
  *
  * You can force values for all available locales to be included in the returned string or array list using the "returnAllLocales" option.
  * 
  * CollectiveAccess stores related, repeating and multilingual data in a fairly complex series of nested structures. get() is intended to faciliate output of data so most of its options are geared towards
  * flattening of data for easy of formatting and display, with commensurate loss of internal structre. Set the "returnWithStructure" option to obtain the "raw" data with all of its internal structure intact. The
  * returned value will be a multidimensional array tailored to the type of data being returned. Typically this array will be indexed first by the id of the record to which the returned data is attached, then
  * by locale_id or code (if "returnAllLocales" is set), then the id specific to the data item (Eg. internal attribute_id for metadata, label_id for labels, Etc.), and finally an array with keys set to data element names
  * and associated values.
  *
  * Return values can be modified using the following options:
  *
  *		[Options controlling type of return value]
  *			returnAsArray = return values in a one-dimensional, numerically indexed array. If not not a string is always returned. [Default is false]
  *			returnWithStructure = return values in a multi-dimensional array mirroring the internal storage structure of CollectiveAccess. [Default is false]
  *
  *		[Options controlling scope of data in return value]
  *			returnAllLocales = Return values from all available locales, rather than just the most appropriate locale for the current user. For string and array return values, returnAllLocales will result in inclusion of additional values. For returnWithStructure, additional entries keys on locale_id or code will be added.  [Default is false]
  *			useLocaleCodes =  For returnWithStructure locale codes (ex. en_US) will be used rather than numeric locale_ids. [Default is false]
  * 			restrictToTypes = For bundles referencing data in related tables (ex. calling ca_entities.idno from a ca_objects result) will restrict returned items to those of the specified types. An array of list item idnos and/or item_ids may be specified. [Default is null]
  *			restrictToRelationshipTypes =  For bundles referencing data in related tables (ex. calling ca_entities.idno from a ca_objects result) will restrict returned items to those related using the specified relationship types. An array of relationship type idnos and/or type_ids may be specified. [Default is null]
  *			excludeTypes = For bundles referencing data in related tables (ex. calling ca_entities.idno from a ca_objects result) will restrict returned items to those *not* of the specified types. An array of list item idnos and/or item_ids may be specified. [Default is null]
  *			excludeRelationshipTypes = For bundles referencing data in related tables (ex. calling ca_entities.idno from a ca_objects result) will restrict returned items to those *not* related using the specified relationship types. An array of relationship type idnos and/or type_ids may be specified. [Default is null]
  *			restrictToType = Synonym for restrictToTypes. [Default is null]
  *			restrictToRelationshipType = Synonym for restrictToRelationshipTypes. [Default is null]
  *			excludeType = Synonym for excludeTypes. [Default is null]
  *			excludeRelationshipType = Synonym for excludeRelationshipTypes. [Default is null]
  *			filters = Array list of elements to filter returned values on. The element must be part of the container being fetched from. For example, when fetching a value from a container element (ex. 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 (ex. "date_type" => "copyright"). Pass only the name of the subelement, not the full path that includes the table and container element. You may 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 or returnWithStructure are set. [Default is null]
  *			assumeDisplayField = For returnWithStructure, return display field for ambiguous preferred label specifiers (ex. ca_entities.preferred_labels => ca_entities.preferred_labels.displayname). If set to false an array with all label fields is returned. [Default is true]
  *			returnURL = When fetching intrinsic value of type FT_MEDIA return URL to media rather than HTML tag. [Default is false]
  *			returnPath = When fetching intrinsic value of type FT_MEDIA return path to media rather than HTML tag. [Default is false] 
  *			unserialize = When fetching intrinsic value of type FT_VARS (serialized variables) return unserialized value. [Default is false]
  *			
  *		[Formatting options for strings and arrays]
  *			template = Display template use when formatting return values. @see http://docs.collectiveaccess.org/wiki/Display_Templates. [Default is null]
  *			delimiter = Characters to place in between repeating values when returning a string
  *			makeLink = Return value as a link to the relevant editor (Providence) or detail (Pawtucket) when bundle references data in a related table; return value as HTML link when value is URL type. [Default is false]
  *			returnAsLink = Synonym for makeLink. [Default is false]
  *			convertCodesToDisplayText = Convert list item_ids text in the user's preferred locale for display. [Default is false]
  *			convertCodesToIdno = Convert list item_ids to idno's (ca_list_items.idno). If convertCodesToDisplayText is also set then it will take precedence. [Default is false]
  *			output = Convert list item_ids to display text in user's preferred locale ("text") or idno ("idno"). This is an easier to type alternative to the convertCodesToDisplayText and convertCodesToIdno options. [Default is null]
  *			sort = Array list of bundles to sort returned values on. Currently sort is only supported when getting related values via simple related <table_name> and <table_name>.related bundle specifiers. Eg. from a ca_objects results you can sort when fetching 'ca_entities', 'ca_entities.related', 'ca_objects.related', etc.. The sortable bundle specifiers are fields with or without tablename. Only those fields returned for the related tables (intrinsics and label fields) are sortable. You cannot currenty sort on attributes. [Default is null]
  *
  *		[Formatting for strings only]
  *			toUpper = Force all values to upper case. [Default is false]
  *			toLower = Force all values to lower case. [Default is false]
  *			makeFirstUpper = Force first character of all values to upper case. [Default is false]
  *			trim = Trim white space from beginning and end of string. [Default is false]
  *			start = Return all values trimmed to start at the specified character. [Default is null]
  *			length = Return all values truncated to a maximum length. [Default is null]
  *			truncate = Return all values from the beginning truncated to a maximum length; equivalent of passing start=0 and length. [Default is null]
  *			ellipsis = Add ellipsis ("...") to truncated values. Values will be set to the truncated length including the ellipsis. Eg. a value truncated to 12 characters will include 9 characters of text and 3 characters of ellipsis. [Default is false]
  *
  *		[Formatting options for hierarchies]
  *			maxLevelsFromTop = Restrict the number of levels returned to the top-most beginning with the root. [Default is null]
  *			maxLevelsFromBottom = Restrict the number of levels returned to the bottom-most starting with the lowest leaf node. [Default is null]
  *			maxLevels = synonym for maxLevelsFromBottom. [Default is null]
  *			removeFirstItems = Number of levels from top of hierarchy before returning. [Default is null]
  *			hierarchyDirection = Order in which to return hierarchical levels. Set to either "asc" or "desc". "Asc"ending returns hierarchy beginning with the root; "desc"ending begins with the child furthest from the root. [Default is asc]
  *			allDescendants = Return all items from the full depth of the hierarchy when fetching children. By default only immediate children are returned. [Default is false]
  *
  *		[Front-end access control]		
  *			checkAccess = Array of access values to filter returned values on. Available for any table with an "access" field (ca_objects, ca_entities, etc.). If omitted no filtering is performed. [Default is null]
  *
  *	@param string $ps_field 
  *	@param array $pa_options Options as described above
  * 	@return mixed String or array
  */
 public function get($ps_field, $pa_options = null)
 {
     $vb_return_as_array = isset($pa_options['returnAsArray']) ? (bool) $pa_options['returnAsArray'] : false;
     $vb_return_with_structure = isset($pa_options['returnWithStructure']) ? (bool) $pa_options['returnWithStructure'] : false;
     if ($vb_return_with_structure) {
         $pa_options['returnAsArray'] = $vb_return_as_array = true;
     }
     // returnWithStructure implies returnAsArray
     // Return primary key of primary table as quickly as possible
     if ($ps_field == $this->ops_table_pk || $ps_field == $this->ops_table_name . '.' . $this->ops_table_pk) {
         $vn_id = $this->opo_engine_result->get($this->ops_table_pk);
         return $vb_return_as_array || $vb_return_with_structure ? array($vn_id) : $vn_id;
     }
     if (isset($pa_options['template']) && $pa_options['template']) {
         return $this->getWithTemplate($pa_options['template'], $pa_options);
     }
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     $va_filters = is_array($pa_options['filters']) ? $pa_options['filters'] : array();
     // Add table name to field specs that lack it
     if (strpos($ps_field, '.') === false && !SearchResult::$opo_datamodel->tableExists($ps_field)) {
         $va_tmp = array($this->ops_table_name, $ps_field);
         $ps_field = $this->ops_table_name . ".{$ps_field}";
     }
     $vb_return_all_locales = isset($pa_options['returnAllLocales']) ? (bool) $pa_options['returnAllLocales'] : false;
     $vs_delimiter = isset($pa_options['delimiter']) ? $pa_options['delimiter'] : ';';
     $vb_unserialize = isset($pa_options['unserialize']) ? (bool) $pa_options['unserialize'] : false;
     $vb_return_url = isset($pa_options['returnURL']) ? (bool) $pa_options['returnURL'] : false;
     $vb_return_path = isset($pa_options['returnPath']) ? (bool) $pa_options['returnPAth'] : false;
     $vb_convert_codes_to_display_text = isset($pa_options['convertCodesToDisplayText']) ? (bool) $pa_options['convertCodesToDisplayText'] : false;
     $vb_convert_codes_to_idno = isset($pa_options['convertCodesToIdno']) ? (bool) $pa_options['convertCodesToIdno'] : false;
     $vb_use_locale_codes = isset($pa_options['useLocaleCodes']) ? (bool) $pa_options['useLocaleCodes'] : false;
     $vb_assume_display_field = isset($pa_options['assumeDisplayField']) ? (bool) $pa_options['assumeDisplayField'] : true;
     if (!($vs_output = isset($pa_options['output']) ? (string) $pa_options['output'] : null)) {
         if ($vb_convert_codes_to_display_text) {
             $vs_output = "text";
         }
         if (!$vs_output && $vb_convert_codes_to_idno) {
             $vs_output = "idno";
         }
     }
     if (!in_array($vs_output, array('text', 'idno', 'value'))) {
         $vs_output = 'value';
     }
     $pa_options['output'] = $vs_output;
     if (!($vb_return_as_link = isset($pa_options['makeLink']) ? (bool) $pa_options['makeLink'] : false)) {
         $vb_return_as_link = isset($pa_options['returnAsLink']) ? (bool) $pa_options['returnAsLink'] : false;
     }
     $pa_options['makeLink'] = $vb_return_as_link;
     $vn_max_levels_from_top = isset($pa_options['maxLevelsFromTop']) ? (int) $pa_options['maxLevelsFromTop'] : null;
     $vn_max_levels_from_bottom = caGetOption(array('maxLevelsFromBottom', 'maxLevels', 'level_limit', 'hierarchy_limit'), $pa_options, null);
     $vn_remove_first_items = isset($pa_options['removeFirstItems']) ? (int) $pa_options['removeFirstItems'] : 0;
     $va_check_access = isset($pa_options['checkAccess']) ? is_array($pa_options['checkAccess']) ? $pa_options['checkAccess'] : array($pa_options['checkAccess']) : null;
     $vs_template = isset($pa_options['template']) ? (string) $pa_options['template'] : null;
     $va_path_components = isset(SearchResult::$s_parsed_field_component_cache[$this->ops_table_name . '/' . $ps_field]) ? SearchResult::$s_parsed_field_component_cache[$this->ops_table_name . '/' . $ps_field] : $this->parseFieldPathComponents($ps_field);
     $va_val_opts = array_merge($pa_options, array('returnAsArray' => $vb_return_as_array, 'returnAllLocales' => $vb_return_all_locales, 'returnWithStructure' => $vb_return_with_structure, 'pathComponents' => $va_path_components, 'delimiter' => $vs_delimiter, 'makeLink' => $vb_return_as_link, 'returnURL' => $vb_return_url, 'returnPath' => $vb_return_path, 'unserialize' => $vb_unserialize, 'convertCodesToDisplayText' => $vb_convert_codes_to_display_text, 'convertCodesToIdno' => $vb_convert_codes_to_idno, 'checkAccess' => $va_check_access, 'template' => $vs_template, 'useLocaleCodes' => $vb_use_locale_codes));
     if ($va_path_components['table_name'] != $this->ops_table_name) {
         $vs_access_chk_key = $va_path_components['table_name'] . ($va_path_components['field_name'] ? '.' . $va_path_components['field_name'] : '');
     } else {
         $vs_access_chk_key = $va_path_components['field_name'];
     }
     if ($va_path_components['field_name'] !== 'access' && caGetBundleAccessLevel($va_path_components['table_name'], $vs_access_chk_key) == __CA_BUNDLE_ACCESS_NONE__) {
         return null;
     }
     if (!(($vs_value = $this->opo_engine_result->get($ps_field, $pa_options)) === false)) {
         if ($vb_return_as_array) {
             if ($vb_return_all_locales) {
                 return array(1 => $vs_value);
             } else {
                 return array($vs_value);
             }
         } else {
             return $vs_value;
         }
     }
     if (!($t_instance = SearchResult::$s_instance_cache[$va_path_components['table_name']])) {
         $t_instance = SearchResult::$s_instance_cache[$va_path_components['table_name']] = SearchResult::$opo_datamodel->getInstanceByTableName($va_path_components['table_name'], true);
     }
     if (!$t_instance) {
         return null;
     }
     // Bad table
     $vn_row_id = $this->opo_engine_result->get($this->ops_table_pk);
     $va_val_opts['primaryKey'] = $t_instance->primaryKey();
     if ($va_path_components['hierarchical_modifier']) {
         if ($vb_assume_display_field && in_array($va_path_components['field_name'], array('preferred_labels', 'nonpreferred_labels')) && !$va_path_components['subfield_name']) {
             $va_path_components['subfield_name'] = $va_path_components['components'][2] = $t_instance->getLabelDisplayField();
         }
         switch ($va_path_components['hierarchical_modifier']) {
             case 'parent':
                 $vs_opt_md5 = caMakeCacheKeyFromOptions($pa_options);
                 if ($va_path_components['related']) {
                     // [RELATED TABLE PARENT]
                     if (!isset(SearchResult::$opa_hierarchy_parent_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']][$vs_opt_md5])) {
                         $this->prefetchHierarchyParents($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     $va_ids = SearchResult::$opa_hierarchy_parent_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']][$vs_opt_md5];
                 } else {
                     // [PRIMARY TABLE PARENT]
                     if (!isset(SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5])) {
                         $this->prefetchHierarchyParents($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     $va_ids = array($vn_row_id);
                 }
                 if (!sizeof($va_ids)) {
                     return $pa_options['returnAsArray'] ? array() : null;
                 }
                 $va_hiers = array();
                 foreach ($va_ids as $vn_id) {
                     $va_parent_ids = array();
                     if (isset(SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_id][$vs_opt_md5]) && is_array(SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_id][$vs_opt_md5])) {
                         if (!is_array($va_parent_ids = SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_id][$vs_opt_md5])) {
                             return $pa_options['returnAsArray'] ? array() : null;
                         }
                     }
                     $va_parent_ids = array_slice($va_parent_ids, 0, 1);
                     if (!($qr_hier = $t_instance->makeSearchResult($va_path_components['table_name'], $va_parent_ids))) {
                         return $pa_options['returnAsArray'] ? array() : null;
                     }
                     $va_tmp = array($va_path_components['table_name']);
                     if ($va_path_components['field_name']) {
                         $va_tmp[] = $va_path_components['field_name'];
                     }
                     if ($va_path_components['subfield_name']) {
                         $va_tmp[] = $va_path_components['subfield_name'];
                     }
                     $vs_hier_fld_name = join(".", $va_tmp);
                     $vs_pk = $t_instance->primaryKey();
                     $vm_val = null;
                     if ($qr_hier->nextHit()) {
                         $vm_val = $qr_hier->get($vs_hier_fld_name, $pa_options);
                     }
                     if ($vm_val) {
                         $va_hiers[] = $vb_return_as_array ? array_shift($vm_val) : $vm_val;
                     }
                 }
                 $vm_val = $vb_return_as_array ? $va_hiers : join($vs_delimiter, $va_hiers);
                 goto filter;
                 break;
             case 'hierarchy':
                 $vs_opt_md5 = caMakeCacheKeyFromOptions($pa_options);
                 // generate the hierarchy
                 if ($va_path_components['related']) {
                     // [RELATED TABLE HIERARCHY]
                     if (!isset(SearchResult::$opa_hierarchy_parent_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']][$vs_opt_md5])) {
                         $this->prefetchHierarchyParents($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     // ids of related items
                     $va_ids = array_values(SearchResult::$opa_hierarchy_parent_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']][$vs_opt_md5]);
                 } else {
                     // [PRIMARY TABLE HIERARCHY]
                     if (!isset(SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5])) {
                         $this->prefetchHierarchyParents($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     $va_ids = array($vn_row_id);
                 }
                 if (!sizeof($va_ids)) {
                     return $pa_options['returnAsArray'] ? array() : null;
                 }
                 $vs_hier_pk_fld = $t_instance->primaryKey();
                 $va_hiers = $va_hier_ids = array();
                 $vs_hierarchy_direction = isset($pa_options['hierarchyDirection']) ? strtolower($pa_options['hierarchyDirection']) : 'asc';
                 if ($t_instance->isHierarchical()) {
                     if ($va_path_components['field_name'] === $vs_hier_pk_fld) {
                         if ($va_path_components['related']) {
                             foreach ($va_ids as $vn_id) {
                                 if (is_array(SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_id][$vs_opt_md5])) {
                                     $va_hier_id_list = array_merge(array($vn_id), SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_id][$vs_opt_md5]);
                                     $va_hier_id_list = array_filter($va_hier_id_list, function ($v) {
                                         return $v > 0;
                                     });
                                     if ($vs_hierarchy_direction === 'asc') {
                                         $va_hier_id_list = array_reverse($va_hier_id_list);
                                     }
                                     if (!is_null($vn_max_levels_from_top)) {
                                         $va_hier_id_list = array_slice($va_hier_id_list, 0, $vn_max_levels_from_top, true);
                                     } elseif (!is_null($vn_max_levels_from_bottom)) {
                                         if (($vn_start = sizeof($va_hier_id_list) - $vn_max_levels_from_bottom) < 0) {
                                             $vn_start = 0;
                                         }
                                         $va_hier_id_list = array_slice($va_hier_id_list, $vn_start, $vn_max_levels_from_bottom, true);
                                     }
                                     $va_hier_ids[] = $va_hier_id_list;
                                 }
                             }
                         } else {
                             // Return ids from hierarchy in order
                             if (is_array(SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5])) {
                                 $va_hier_ids = array_merge(array($vn_row_id), SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5]);
                             } else {
                                 $va_hier_ids = array($vn_row_id);
                             }
                             if (($vn_type_id = $this->get($va_path_components['table_name'] . ".type_id")) && ($va_restrict_to_types = caGetOption('restrictToTypes', $pa_options, null))) {
                                 $va_types = caMakeTypeIDList($va_path_components['table_name'], $va_restrict_to_types);
                                 if (!in_array($vn_type_id, $va_types)) {
                                     array_shift($va_hier_ids);
                                 }
                             }
                             if (!is_null($vn_max_levels_from_top)) {
                                 $va_hier_ids = array_slice($va_hier_ids, 0, $vn_max_levels_from_top, true);
                             } elseif (!is_null($vn_max_levels_from_bottom)) {
                                 if (($vn_start = sizeof($va_hier_ids) - $vn_max_levels_from_bottom) < 0) {
                                     $vn_start = 0;
                                 }
                                 $va_hier_ids = array_slice($va_hier_ids, $vn_start, $vn_max_levels_from_bottom, true);
                             }
                             if ($vs_hierarchy_direction === 'asc') {
                                 $va_hier_ids = array_reverse($va_hier_ids);
                             }
                         }
                         $vm_val = $vb_return_as_array ? $va_hier_ids : join($vs_delimiter, $va_hier_ids);
                         goto filter;
                     } else {
                         $vs_field_spec = join('.', array_values($va_path_components['components']));
                         $va_ancestor_id_list = $this->get($va_path_components['table_name'] . '.hierarchy.' . $vs_hier_pk_fld, array_merge($pa_options, array('returnAsArray' => true, 'returnAsLink' => false, 'returnAllLocales' => false)));
                         if (!is_array($va_ancestor_id_list)) {
                             return $vb_return_as_array ? array() : null;
                         }
                         if (!$va_path_components['related']) {
                             $va_ancestor_id_list = array($va_ancestor_id_list);
                         }
                         $va_hier_list = array();
                         foreach ($va_ancestor_id_list as $va_ancestor_ids) {
                             if ($vn_remove_first_items > 0) {
                                 $va_ancestor_ids = array_slice($va_ancestor_ids, $vn_remove_first_items);
                             }
                             $va_hier_item = array();
                             if ($qr_hier = caMakeSearchResult($va_path_components['table_name'], $va_ancestor_ids)) {
                                 while ($qr_hier->nextHit()) {
                                     $va_hier_item += $qr_hier->get($vs_field_spec, array('returnWithStructure' => true, 'returnAllLocales' => true, 'useLocaleCodes' => $pa_options['useLocaleCodes']));
                                 }
                                 if (!is_null($vn_max_levels_from_top)) {
                                     $va_hier_item = array_slice($va_hier_item, 0, $vn_max_levels_from_top, true);
                                 } elseif (!is_null($vn_max_levels_from_bottom)) {
                                     if (($vn_start = sizeof($va_hier_item) - $vn_max_levels_from_bottom) < 0) {
                                         $vn_start = 0;
                                     }
                                     $va_hier_item = array_slice($va_hier_item, $vn_start, $vn_max_levels_from_bottom, true);
                                 }
                                 $va_hier_list[] = $va_hier_item;
                             }
                         }
                     }
                 }
                 $va_acc = array();
                 foreach ($va_hier_list as $vn_h => $va_hier_item) {
                     if (!$vb_return_all_locales) {
                         $va_hier_item = caExtractValuesByUserLocale($va_hier_item);
                     }
                     if ($vb_return_with_structure) {
                         $va_acc[] = $va_hier_item;
                     } else {
                         $va_acc = $this->_flattenArray($va_hier_item, $pa_options);
                     }
                 }
                 $vm_val = $pa_options['returnAsArray'] ? $va_acc : join($vs_delimiter, $va_acc);
                 goto filter;
                 break;
             case 'children':
                 // grab children
                 $vs_opt_md5 = caMakeCacheKeyFromOptions($pa_options);
                 if ($va_path_components['related']) {
                     // [RELATED TABLE CHILDREN]
                     if (!isset(SearchResult::$opa_hierarchy_children_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']][$vs_opt_md5])) {
                         $this->prefetchHierarchyChildren($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     $va_ids = SearchResult::$opa_hierarchy_children_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']][$vs_opt_md5];
                 } else {
                     // [PRIMARY TABLE CHILDREN]
                     if (!isset(SearchResult::$opa_hierarchy_children_prefetch_cache[$this->ops_table_name][$vn_row_id][$vs_opt_md5])) {
                         $this->prefetchHierarchyChildren($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     $va_ids = array($vn_row_id);
                 }
                 $va_hier_list = array();
                 foreach ($va_ids as $vn_id) {
                     if (!is_array(SearchResult::$opa_hierarchy_children_prefetch_cache[$va_path_components['table_name']][$vn_id][$vs_opt_md5]) || !sizeof(SearchResult::$opa_hierarchy_children_prefetch_cache[$va_path_components['table_name']][$vn_id][$vs_opt_md5])) {
                         continue;
                     }
                     $qr_hier = $t_instance->makeSearchResult($va_path_components['table_name'], SearchResult::$opa_hierarchy_children_prefetch_cache[$va_path_components['table_name']][$vn_id][$vs_opt_md5]);
                     $va_tmp = array($va_path_components['table_name']);
                     if ($va_path_components['field_name']) {
                         $va_tmp[] = $va_path_components['field_name'];
                     }
                     if ($va_path_components['subfield_name']) {
                         $va_tmp[] = $va_path_components['subfield_name'];
                     }
                     $vs_hier_fld_name = join(".", $va_tmp);
                     $vs_pk = $t_instance->primaryKey();
                     while ($qr_hier->nextHit()) {
                         $vm_val = $qr_hier->get($vs_hier_fld_name, $pa_options);
                         $va_hier_list[$qr_hier->get($va_path_components['table_name'] . '.' . $vs_pk)] = $vb_return_as_array ? array_shift($vm_val) : $vm_val;
                     }
                 }
                 if (!$vb_return_as_array) {
                     return join($vs_delimiter, $va_hier_list);
                 }
                 $vm_val = $va_hier_list;
                 goto filter;
                 break;
             case 'siblings':
                 // grab siblings
                 $vs_opt_md5 = caMakeCacheKeyFromOptions($pa_options);
                 if ($va_path_components['related']) {
                     // [RELATED TABLE SIBLINGS]
                     if (!isset(SearchResult::$opa_hierarchy_siblings_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']][$vs_opt_md5])) {
                         $this->prefetchHierarchySiblings($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     $va_ids = SearchResult::$opa_hierarchy_siblings_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']][$vs_opt_md5];
                 } else {
                     // [PRIMARY TABLE SIBLINGS]
                     if (!isset(SearchResult::$opa_hierarchy_siblings_prefetch_cache[$this->ops_table_name][$vn_row_id][$vs_opt_md5])) {
                         $this->prefetchHierarchySiblings($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     $va_ids = array($vn_row_id);
                 }
                 $va_hier_list = array();
                 foreach ($va_ids as $vn_id) {
                     if (!is_array(SearchResult::$opa_hierarchy_siblings_prefetch_cache[$va_path_components['table_name']][$vn_id][$vs_opt_md5]) || !sizeof(SearchResult::$opa_hierarchy_siblings_prefetch_cache[$va_path_components['table_name']][$vn_id][$vs_opt_md5])) {
                         continue;
                     }
                     $qr_hier = $t_instance->makeSearchResult($va_path_components['table_name'], SearchResult::$opa_hierarchy_siblings_prefetch_cache[$va_path_components['table_name']][$vn_id][$vs_opt_md5]);
                     $va_tmp = array($va_path_components['table_name']);
                     if ($va_path_components['field_name']) {
                         $va_tmp[] = $va_path_components['field_name'];
                     }
                     if ($va_path_components['subfield_name']) {
                         $va_tmp[] = $va_path_components['subfield_name'];
                     }
                     $vs_hier_fld_name = join(".", $va_tmp);
                     $vs_pk = $t_instance->primaryKey();
                     while ($qr_hier->nextHit()) {
                         $vm_val = $qr_hier->get($vs_hier_fld_name, $pa_options);
                         $va_hier_list[$qr_hier->get($va_path_components['table_name'] . '.' . $vs_pk)] = $vb_return_as_array ? array_shift($vm_val) : $vm_val;
                     }
                 }
                 if (!$vb_return_as_array) {
                     $vm_val = join($vs_delimiter, $va_hier_list);
                     goto filter;
                 }
                 $vm_val = $va_hier_list;
                 goto filter;
                 break;
         }
         goto filter;
     }
     if ($va_path_components['related']) {
         //
         // [RELATED TABLE]
         //
         $vb_return_cache_options = false;
         if (caGetOption('returnCacheOptions', $pa_options, false)) {
             $vb_return_cache_options = true;
             unset($pa_options['returnCacheOptions']);
         }
         $vs_opt_md5 = caMakeCacheKeyFromOptions($va_get_opts = array_merge($pa_options, array('dontReturnLabels' => false)));
         if ($vb_return_cache_options) {
             return $va_get_opts;
         }
         if (!isset(self::$s_rel_prefetch_cache[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']][$vs_opt_md5])) {
             $this->prefetchRelated($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $va_get_opts);
         }
         $va_related_items = self::$s_rel_prefetch_cache[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']][$vs_opt_md5];
         if (!is_array($va_related_items)) {
             return $vb_return_with_structure || $vb_return_as_array ? array() : null;
         }
         $vm_val = $this->_getRelatedValue($va_related_items, $va_val_opts);
         goto filter;
     } else {
         if (!$va_path_components['hierarchical_modifier']) {
             //
             // [PRIMARY TABLE] Created on
             //
             if ($va_path_components['field_name'] == 'created') {
                 if (!isset(self::$s_timestamp_cache['created_on'][$this->ops_table_name][$vn_row_id])) {
                     $this->prefetchChangeLogData($this->ops_table_name, $this->opo_engine_result->currentRow(), $this->getOption('prefetch'));
                 }
                 if ($vb_return_as_array) {
                     if ($va_path_components['subfield_name']) {
                         $vm_val = [self::$s_timestamp_cache['created_on'][$this->ops_table_name][$vn_row_id][$va_path_components['subfield_name']]];
                     } else {
                         $vm_val = self::$s_timestamp_cache['created_on'][$this->ops_table_name][$vn_row_id];
                     }
                     goto filter;
                 } else {
                     $vs_subfield = $va_path_components['subfield_name'] ? $va_path_components['subfield_name'] : 'timestamp';
                     $vm_val = self::$s_timestamp_cache['created_on'][$this->ops_table_name][$vn_row_id][$vs_subfield];
                     if ($vs_subfield == 'timestamp') {
                         $this->opo_tep->init();
                         $this->opo_tep->setUnixTimestamps($vm_val, $vm_val);
                         $vm_val = $this->opo_tep->getText($pa_options);
                     }
                     goto filter;
                 }
             }
             //
             // [PRIMARY TABLE] Last modified on
             //
             if ($va_path_components['field_name'] == 'lastModified') {
                 if (!isset(self::$s_timestamp_cache['last_changed'][$this->ops_table_name][$vn_row_id])) {
                     $this->prefetchChangeLogData($this->ops_table_name, $this->opo_engine_result->currentRow(), $this->getOption('prefetch'));
                 }
                 if ($vb_return_as_array) {
                     if ($va_path_components['subfield_name']) {
                         $vm_val = [self::$s_timestamp_cache['last_changed'][$this->ops_table_name][$vn_row_id][$va_path_components['subfield_name']]];
                     } else {
                         $vm_val = self::$s_timestamp_cache['last_changed'][$this->ops_table_name][$vn_row_id];
                     }
                     goto filter;
                 } else {
                     $vs_subfield = $va_path_components['subfield_name'] ? $va_path_components['subfield_name'] : 'timestamp';
                     $vm_val = self::$s_timestamp_cache['last_changed'][$this->ops_table_name][$vn_row_id][$vs_subfield];
                     if ($vs_subfield == 'timestamp') {
                         $this->opo_tep->init();
                         $this->opo_tep->setUnixTimestamps($vm_val, $vm_val);
                         $vm_val = $this->opo_tep->getText($pa_options);
                     }
                     goto filter;
                 }
             }
             $vs_opt_md5 = caMakeCacheKeyFromOptions($pa_options);
             //
             // [PRIMARY TABLE] Preferred/nonpreferred labels
             //
             if (in_array($va_path_components['field_name'], array('preferred_labels', 'nonpreferred_labels')) && $t_instance instanceof LabelableBaseModelWithAttributes) {
                 $vs_label_table_name = $t_instance->getLabelTableName();
                 if (!isset(self::$s_prefetch_cache[$vs_label_table_name][$vn_row_id][$vs_opt_md5])) {
                     $this->prefetchLabels($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                 }
                 $vm_val = $this->_getLabelValue(self::$s_prefetch_cache[$vs_label_table_name][$vn_row_id][$vs_opt_md5], $t_instance, $va_val_opts);
                 goto filter;
             }
             if ($t_instance->hasField($va_path_components['field_name'])) {
                 $va_val_opts['fieldInfo'] = $t_instance->getFieldInfo($va_path_components['field_name']);
                 //
                 // [PRIMARY TABLE] Plain old intrinsic
                 //
                 if (!isset(self::$s_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5])) {
                     $this->prefetch($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                 }
                 $vm_val = $this->_getIntrinsicValue(self::$s_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5], $t_instance, $va_val_opts);
                 goto filter;
             } elseif (method_exists($t_instance, 'isValidBundle') && !$t_instance->hasElement($va_path_components['field_name'], null, false, array('dontCache' => false)) && $t_instance->isValidBundle($va_path_components['field_name'])) {
                 //
                 // [PRIMARY TABLE] Special bundle
                 //
                 if (!isset(self::$s_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5])) {
                     $this->prefetch($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                 }
                 $vm_val = $t_instance->renderBundleForDisplay($va_path_components['field_name'], $vn_row_id, self::$s_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5], $va_val_opts);
                 goto filter;
             } else {
                 //
                 // [PRIMARY TABLE] Metadata attribute
                 //
                 if ($t_instance instanceof BaseModelWithAttributes && isset($va_path_components['field_name']) && $va_path_components['field_name'] && ($t_element = $t_instance->_getElementInstance($va_path_components['field_name']))) {
                     $vn_element_id = $t_element->getPrimaryKey();
                 } else {
                     return $pa_options['returnAsArray'] ? array() : null;
                 }
                 if (!isset(ca_attributes::$s_get_attributes_cache[(int) $this->opn_table_num . '/' . (int) $vn_row_id][(int) $vn_element_id])) {
                     $va_element_ids = $vn_element_id ? array($vn_element_id) : null;
                     if (is_array($va_prefetch_attributes = $this->getOption('prefetchAttributes')) && sizeof($va_prefetch_attributes)) {
                         $va_element_ids = array_unique($va_element_ids + $va_prefetch_attributes);
                     }
                     ca_attributes::prefetchAttributes($this->opo_subject_instance->getDb(), $this->opn_table_num, $this->getRowIDsToPrefetch($this->opo_engine_result->currentRow(), $this->getOption('prefetch')), $va_element_ids, array('dontFetchAlreadyCachedValues' => true));
                 }
                 $va_attributes = ca_attributes::getAttributes($this->opo_subject_instance->getDb(), $this->opn_table_num, $vn_row_id, array($vn_element_id), array());
                 $vm_val = $this->_getAttributeValue($va_attributes[$vn_element_id], $t_instance, $va_val_opts);
                 goto filter;
             }
         }
     }
     filter:
     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 = SearchResult::$s_instance_cache[$va_tmp[0]])) {
             $t_instance = SearchResult::$s_instance_cache[$va_tmp[0]] = SearchResult::$opo_datamodel->getInstanceByTableName($va_tmp[0], true);
         }
         if ($t_instance) {
             $va_keepers = array();
             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?
                     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, 'alwaysReturnItemID' => true));
                 if (is_array($va_filter_values)) {
                     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] = $vm_val[$vn_id];
             }
             return $va_filtered_vals;
         }
     }
     return $vm_val;
 }
示例#12
0
if (!$t_list->load(array('list_code' => 'place_hierarchies'))) {
    $t_list->setMode(ACCESS_WRITE);
    $t_list->set('list_code', 'place_hierarchies');
    $t_list->set('is_system_list', 1);
    $t_list->set('is_hierarchical', 1);
    $t_list->set('use_as_vocabulary', 0);
    $t_list->insert();
    if ($t_list->numErrors()) {
        print "[Error] couldn't create ca_list row for place hierarchies: " . join('; ', $t_list->getErrors()) . "\n";
        die;
    }
    $t_list->addLabel(array('name' => 'Place hierarchies'), $pn_en_locale_id, null, true);
}
$vn_list_id = $t_list->getPrimaryKey();
// create place hierarchy
if (!($vn_tgn_id = caGetListItemID('place_hierarchies', 'tgn'))) {
    $t_tgn = $t_list->addItem('tgn', true, false, null, null, 'tgn');
    $t_tgn->addLabel(array('name_singular' => 'Thesaurus of Geographic Names', 'name_plural' => 'Thesaurus of Geographic Names'), $pn_en_locale_id, null, true);
    $vn_tgn_id = $t_tgn->getPrimaryKey();
} else {
    $t_tgn = new ca_list_items($vn_tgn_id);
}
// Create list for place types (if it doesn't exist already)
$t_place_types = new ca_lists();
if (!$t_place_types->load(array('list_code' => 'tgn_place_types'))) {
    $t_place_types->setMode(ACCESS_WRITE);
    $t_place_types->set('list_code', 'tgn_place_types');
    $t_place_types->set('is_system_list', 1);
    $t_place_types->set('is_hierarchical', 1);
    $t_place_types->set('use_as_vocabulary', 1);
    $t_place_types->insert();
示例#13
0
 /**
  * Returns a value from the query result. This can be a single value if it is a field in the subject table (eg. objects table in an objects search), or
  * perhaps multiple related values (eg. related entities in an objects search). By default get() always returns a single value; for fields with multiple values
  * the value will be the first value encountered when loading the field data. 
  *
  * You can fetch the values of attributes attached to the subject row (ie. if you're searching for ca_objects rows, the subject row is the ca_objects row)
  * by use the "virtual" field name <subject_table_name>.<element_code> (ex. ca_objects.date_created)
  * If the attribute is a multi-value container then you can fetch a specific value using the format <subject_table_name>.<attribute_element_code>/<value_element_code>
  * For example, if you want to get the "date_value" value out of a "date" attribute attached to a ca_objects row, then you'd call get()
  * with this fieldname: ca_objects.date/date_value
  *
  * If you want to get the other values for a multiple-value fields use the following options:
  *
  *		returnAsArray = if true, return an array, otherwise return a string (default is false)
  *		template = formats attribute values; precede element codes with a caret ("^"). Eg. "^address1<br/>^city, ^state ^postalcode ^country"; only used when returnAsArray is false and a scalar is therefore to be returned.
  *		delimiter = 
  *		returnAllLocales = 
  *		convertCodesToDisplayText = if true then item_ids are automatically converted to display text in the current locale; default is false (return item_ids raw)
  *
  * 		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
  *		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
  *
  *		exclude_relationship_types = omits any items related to the current row with any of the specified types from the returned set of its. 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
  *
  *		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.
  *				If $ps_field is set to refer to a URL metadata element and returnAsLink is set then the returned values will be HTML links using the URL value.
  *		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.
  *
  *		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.
  *		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.
  *
  *		maxLevelsFromTop = for hierarchical gets, restricts the number of levels returned to the top-most starting with the root.
  *		maxLevelsFromBottom = for hierarchical gets, restricts the number of levels returned to the bottom-most starting with the lowest leaf node.
  *		maxLevels = synonym for maxLevelsFromBottom
  */
 public function get($ps_field, $pa_options = null)
 {
     $vb_return_as_array = caGetOption('returnAsArray', $pa_options, false, array('castTo' => 'bool'));
     $va_filters = caGetOption('filters', $pa_options, array(), array('castTo' => 'array'));
     $vm_val = self::_get($ps_field, $pa_options);
     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->opo_datamodel->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, 'alwaysReturnItemID' => true));
                 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] = $vm_val[$vn_id];
             }
             return $va_filtered_vals;
         }
     }
     return $vm_val;
 }
示例#14
0
 /**
  *
  */
 public function getPresetsJavascript($ps_field_prefix, $pa_options = null)
 {
     if (!($vn_element_id = $this->getPrimaryKey())) {
         return null;
     }
     // element must be loaded
     $o_presets = Configuration::load(__CA_APP_DIR__ . "/conf/attributePresets.conf");
     if ($va_presets = $o_presets->getAssoc($this->get('element_code'))) {
         $va_elements = $this->getElementsInSet();
         $va_element_code_to_ids = $va_element_info = array();
         foreach ($va_elements as $va_element) {
             $va_element_code_to_ids[$va_element['element_code']] = $va_element['element_id'];
             $va_element_info[$va_element['element_code']] = $va_element;
         }
         foreach ($va_presets as $vs_code => $va_preset) {
             foreach ($va_preset['values'] as $vs_k => $vs_v) {
                 if (!$va_element_code_to_ids[$vs_k]) {
                     continue;
                 }
                 switch ((int) $va_element_info[$vs_k]['datatype']) {
                     case 3:
                         $va_presets[$vs_code]['values'][$va_element_code_to_ids[$vs_k]] = caGetListItemID($va_element_info[$vs_k]['list_id'], $vs_v);
                         break;
                     default:
                         $va_presets[$vs_code]['values'][$va_element_code_to_ids[$vs_k]] = $vs_v;
                         break;
                 }
                 unset($va_presets[$vs_code]['values'][$vs_k]);
             }
         }
         $vs_buf .= "\n\n\tfunction caHandlePresets_{$ps_field_prefix}_(s, n) {\n\t\tvar presets = " . json_encode($va_presets) . ";\n\t\tif (presets[s]){ \n\t\t\tfor(var k in presets[s]['values']) {\n\t\t\t\tif (!presets[s]['values'][k]) { continue; }\n\t\t\t\tjQuery('#{$ps_field_prefix}' + '_' + k + '_' + n + '').val(presets[s]['values'][k]);\n\t\t\t}\n\t\t}\n\t}\n";
         return $vs_buf;
     }
     return null;
 }
示例#15
0
 /**
  * Returns list of sets subject to options
  *
  * @param array $pa_options Array of options. Supported options are:
  *			table - if set, list is restricted to sets that can contain the specified item. You can pass a table name or number. If omitted sets containing any content will be returned.
  *			setType - Restricts returned sets to those of the specified type. You can pass a type_id or list item code for the set type. If omitted sets are returned regardless of type.
  *			user_id - Restricts returned sets to those accessible by the current user. If omitted then all sets, regardless of access are returned.
  *			access - Restricts returned sets to those with at least the specified access level for the specified user. If user_id is omitted then this option has no effect. If user_id is set and this option is omitted, then sets where the user has at least read access will be returned. 
  *			checkAccess - Restricts returned sets to those with an public access level with the specified values. If omitted sets are returned regardless of public access (ca_sets.access) value. Can be a single value or array if you wish to filter on multiple public access values.
  *			row_id = if set to an integer only sets containing the specified row are returned
  *			setIDsOnly = if set to true only set_id values are returned, in a simple array
  *			omitCounts = 
  *			all = 
  *			allUsers =
  *			publicUsers =
  *			name = 
  * @return array A list of sets keyed by set_id and then locale_id. Keys for the per-locale value array include: set_id, set_code, status, public access, owner user_id, content table_num, set type_id, set name, number of items in the set (item_count), set type name for display and set content type name for display. If setIDsOnly option is set then a simple array of set_id values is returned instead.
  */
 public function getSets($pa_options = null)
 {
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     $pm_table_name_or_num = isset($pa_options['table']) ? $pa_options['table'] : null;
     $pm_type = isset($pa_options['setType']) ? $pa_options['setType'] : null;
     $pn_user_id = isset($pa_options['user_id']) ? (int) $pa_options['user_id'] : null;
     $pn_access = isset($pa_options['access']) ? $pa_options['access'] : null;
     $pb_set_ids_only = isset($pa_options['setIDsOnly']) ? (bool) $pa_options['setIDsOnly'] : false;
     $pb_omit_counts = isset($pa_options['omitCounts']) ? (bool) $pa_options['omitCounts'] : false;
     $ps_set_name = isset($pa_options['name']) ? $pa_options['name'] : null;
     $pn_row_id = isset($pa_options['row_id']) && (int) $pa_options['row_id'] ? (int) $pa_options['row_id'] : null;
     $ps_sort = caGetOption('sort', $pa_options, null);
     $ps_sort_direction = caGetOption('sortDirection', $pa_options, null);
     $pa_public_access = isset($pa_options['checkAccess']) ? $pa_options['checkAccess'] : null;
     if ($pa_public_access && is_numeric($pa_public_access) && !is_array($pa_public_access)) {
         $pa_public_access = array($pa_public_access);
     }
     for ($vn_i = 0; $vn_i < sizeof($pa_public_access); $vn_i++) {
         $pa_public_access[$vn_i] = intval($pa_public_access[$vn_i]);
     }
     if ($pm_table_name_or_num && !($vn_table_num = $this->_getTableNum($pm_table_name_or_num))) {
         return null;
     }
     $va_extra_joins = array();
     $o_db = $this->getDb();
     $va_sql_wheres = array("(cs.deleted = 0)");
     $va_sql_params = array();
     if ($vn_table_num) {
         $va_sql_wheres[] = "(cs.table_num = ?)";
         $va_sql_params[] = (int) $vn_table_num;
     }
     if ($pb_set_ids_only) {
         $va_sql_selects = array('cs.set_id');
     } else {
         $va_sql_selects = array('cs.set_id', 'cs.set_code', 'cs.status', 'cs.access', 'cs.user_id', 'cs.table_num', 'cs.type_id', 'csl.label_id', 'csl.name', 'csl.locale_id', 'l.language', 'l.country', 'u.fname', 'u.lname', 'u.email');
     }
     if (isset($pa_options['all']) && $pa_options['all']) {
         $va_sql_wheres[] = "(cs.user_id IN (SELECT user_id FROM ca_users WHERE userclass != 255))";
     } elseif (isset($pa_options['allUsers']) && $pa_options['allUsers']) {
         $va_sql_wheres[] = "(cs.user_id IN (SELECT user_id FROM ca_users WHERE userclass = 0))";
     } elseif (isset($pa_options['publicUsers']) && $pa_options['publicUsers']) {
         $va_sql_wheres[] = "(cs.user_id IN (SELECT user_id FROM ca_users WHERE userclass = 1))";
     } else {
         if ($pn_user_id && !$this->getAppConfig()->get('dont_enforce_access_control_for_ca_sets')) {
             $o_dm = $this->getAppDatamodel();
             $t_user = $o_dm->getInstanceByTableName('ca_users', true);
             $t_user->load($pn_user_id);
             if ($t_user->getPrimaryKey()) {
                 $vs_access_sql = $pn_access > 0 ? " AND (access >= " . intval($pn_access) . ")" : "";
                 if (is_array($va_groups = $t_user->getUserGroups()) && sizeof($va_groups)) {
                     $vs_sql = "(\n\t\t\t\t\t\t\t(cs.user_id = " . intval($pn_user_id) . ") OR \n\t\t\t\t\t\t\t(cs.set_id IN (\n\t\t\t\t\t\t\t\t\tSELECT set_id \n\t\t\t\t\t\t\t\t\tFROM ca_sets_x_user_groups \n\t\t\t\t\t\t\t\t\tWHERE \n\t\t\t\t\t\t\t\t\t\tgroup_id IN (" . join(',', array_keys($va_groups)) . ") {$vs_access_sql}\n\t\t\t\t\t\t\t\t\t\tAND\n\t\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\t (sdatetime IS NULL AND edatetime IS NULL)\n\t\t\t\t\t\t\t\t\t\t\t OR \n\t\t\t\t\t\t\t\t\t\t\t (\n\t\t\t\t\t\t\t\t\t\t\t\tsdatetime <= " . time() . " AND edatetime >= " . time() . "\n\t\t\t\t\t\t\t\t\t\t\t )\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t)\n\t\t\t\t\t\t)";
                 } else {
                     $vs_sql = "(cs.user_id = {$pn_user_id})";
                 }
                 $vs_sql .= " OR (cs.set_id IN (\n\t\t\t\t\t\t\t\t\t\t\tSELECT set_id \n\t\t\t\t\t\t\t\t\t\t\tFROM ca_sets_x_users \n\t\t\t\t\t\t\t\t\t\t\tWHERE \n\t\t\t\t\t\t\t\t\t\t\t\tuser_id = {$pn_user_id} {$vs_access_sql}\n\t\t\t\t\t\t\t\t\t\t\t\tAND\n\t\t\t\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\t\t\t (sdatetime IS NULL AND edatetime IS NULL)\n\t\t\t\t\t\t\t\t\t\t\t\t\t OR \n\t\t\t\t\t\t\t\t\t\t\t\t\t (\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsdatetime <= " . time() . " AND edatetime >= " . time() . "\n\t\t\t\t\t\t\t\t\t\t\t\t\t )\n\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t)";
                 $va_sql_wheres[] = "({$vs_sql})";
             }
         }
     }
     if (!is_null($pa_public_access) && is_array($pa_public_access) && sizeof($pa_public_access)) {
         $va_sql_wheres[] = "(cs.access IN (?))";
         $va_sql_params[] = $pa_public_access;
     }
     if (isset($pm_type) && $pm_type) {
         if (is_numeric($pm_type)) {
             $va_sql_wheres[] = "(cs.type_id = ?)";
             $va_sql_params[] = (int) $pm_type;
         } else {
             # --- look up code of set type
             $t_list = new ca_lists();
             $vn_type_id = $t_list->getItemIDFromList("set_types", $pm_type);
             if ($vn_type_id) {
                 $va_sql_wheres[] = "(cs.type_id = ?)";
                 $va_sql_params[] = (int) $vn_type_id;
             }
         }
     }
     if ($va_restrict_to_types = caGetOption('restrict_to_types', $pa_options, false)) {
         $va_restrict_to_type_ids = array();
         foreach ($va_restrict_to_types as $vm_type) {
             if (is_numeric($vm_type)) {
                 $va_restrict_to_type_ids[] = (int) $vm_type;
             } else {
                 # --- look up code of set type
                 $vn_type_id = caGetListItemID('set_types', $pm_type);
                 if ($vn_type_id) {
                     $va_restrict_to_type_ids[] = (int) $vn_type_id;
                 }
             }
         }
         if (sizeof($va_restrict_to_type_ids)) {
             $va_sql_wheres[] = "(cs.type_id IN (?))";
             $va_sql_params[] = $va_restrict_to_type_ids;
         }
     }
     if ($pn_row_id > 0) {
         $va_sql_wheres[] = "((csi.row_id = ?) AND (csi.table_num = ?))";
         $va_extra_joins[] = "INNER JOIN ca_set_items AS csi ON cs.set_id = csi.set_id";
         $va_sql_selects[] = 'csi.item_id';
         $va_sql_params[] = (int) $pn_row_id;
         $va_sql_params[] = (int) $vn_table_num;
     }
     if ($ps_set_name) {
         $va_sql_wheres[] = "(csl.name = ?)";
         $va_sql_params[] = (string) $ps_set_name;
     }
     if (!$pb_set_ids_only && !$pb_omit_counts) {
         // get set item counts
         $qr_table_nums = $o_db->query("\n\t\t\t\tSELECT DISTINCT cs.table_num \n\t\t\t\tFROM ca_sets cs\n\t\t\t\tINNER JOIN ca_set_items AS csi ON cs.set_id = csi.set_id\n\t\t\t\t" . (sizeof($va_sql_wheres) ? 'WHERE ' : '') . "\n\t\t\t\t" . join(' AND ', $va_sql_wheres) . "\n\t\t\t", $va_sql_params);
         $va_item_counts = array();
         while ($qr_table_nums->nextRow()) {
             $o_dm = $this->getAppDatamodel();
             $t_instance = $o_dm->getInstanceByTableNum($vn_table_num = (int) $qr_table_nums->get('table_num'), true);
             if (!$t_instance) {
                 continue;
             }
             $va_item_sql_params = $va_sql_params;
             $va_item_wheres = $va_sql_wheres;
             $va_item_wheres[] = "(cs.table_num = {$vn_table_num})";
             if ($t_instance->hasField('deleted')) {
                 $va_item_wheres[] = "(t.deleted = 0)";
             }
             if (!is_null($pa_public_access) && is_array($pa_public_access) && sizeof($pa_public_access)) {
                 $va_item_wheres[] = "(t.access IN (?))";
                 $va_item_sql_params[] = $pa_public_access;
             }
             $qr_res = $o_db->query("\n\t\t\t\t\tSELECT cs.set_id, count(distinct row_id) item_count\n\t\t\t\t\tFROM ca_sets cs\n\t\t\t\t\tINNER JOIN ca_set_items AS csi ON cs.set_id = csi.set_id\n\t\t\t\t\tINNER JOIN " . $t_instance->tableName() . " AS t ON t." . $t_instance->primaryKey() . " = csi.row_id\n\t\t\t\t\t" . (sizeof($va_item_wheres) ? 'WHERE ' : '') . "\n\t\t\t\t\t" . join(' AND ', $va_item_wheres) . "\n\t\t\t\t\tGROUP BY cs.set_id\n\t\t\t\t", $va_item_sql_params);
             while ($qr_res->nextRow()) {
                 $va_item_counts[(int) $qr_res->get('set_id')] = (int) $qr_res->get('item_count');
             }
         }
         // get sets
         $qr_res = $o_db->query("\n\t\t\t\tSELECT " . join(', ', $va_sql_selects) . "\n\t\t\t\tFROM ca_sets cs\n\t\t\t\tLEFT JOIN ca_set_labels AS csl ON cs.set_id = csl.set_id\n\t\t\t\tLEFT JOIN ca_locales AS l ON csl.locale_id = l.locale_id\n\t\t\t\tINNER JOIN ca_users AS u ON cs.user_id = u.user_id\n\t\t\t\t" . join("\n", $va_extra_joins) . "\n\t\t\t\t" . (sizeof($va_sql_wheres) ? 'WHERE ' : '') . "\n\t\t\t\t" . join(' AND ', $va_sql_wheres) . "\n\t\t\t\tORDER BY csl.name\n\t\t\t", $va_sql_params);
         $va_sets = array();
         $va_type_name_cache = array();
         $t_list = new ca_lists();
         while ($qr_res->nextRow()) {
             $vn_table_num = $qr_res->get('table_num');
             if (!isset($va_type_name_cache[$vn_table_num]) || !($vs_set_type = $va_type_name_cache[$vn_table_num])) {
                 $vs_set_type = $va_type_name_cache[$vn_table_num] = $this->getSetContentTypeName($vn_table_num, array('number' => 'plural'));
             }
             $vs_type = $t_list->getItemFromListForDisplayByItemID('set_types', $qr_res->get('type_id'));
             $va_sets[$qr_res->get('set_id')][$qr_res->get('locale_id')] = array_merge($qr_res->getRow(), array('item_count' => intval($va_item_counts[$qr_res->get('set_id')]), 'set_content_type' => $vs_set_type, 'set_type' => $vs_type));
         }
         return $va_sets;
     } else {
         if ($pb_set_ids_only) {
             // get sets
             $qr_res = $o_db->query("\n\t\t\t\t\tSELECT " . join(', ', $va_sql_selects) . "\n\t\t\t\t\tFROM ca_sets cs\n\t\t\t\t\tINNER JOIN ca_users AS u ON cs.user_id = u.user_id\n\t\t\t\t\tLEFT JOIN ca_set_labels AS csl ON cs.set_id = csl.set_id\n\t\t\t\t\t" . join("\n", $va_extra_joins) . "\n\t\t\t\t\t" . (sizeof($va_sql_wheres) ? 'WHERE ' : '') . "\n\t\t\t\t\t" . join(' AND ', $va_sql_wheres) . "\n\t\t\t\t\tORDER BY csl.name\n\t\t\t\t", $va_sql_params);
             return $qr_res->getAllFieldValues("set_id");
         } else {
             $qr_res = $o_db->query("\n\t\t\t\t\tSELECT " . join(', ', $va_sql_selects) . "\n\t\t\t\t\tFROM ca_sets cs\n\t\t\t\t\tINNER JOIN ca_users AS u ON cs.user_id = u.user_id\n\t\t\t\t\tLEFT JOIN ca_set_labels AS csl ON cs.set_id = csl.set_id\n\t\t\t\t\tLEFT JOIN ca_locales AS l ON csl.locale_id = l.locale_id\n\t\t\t\t\t" . join("\n", $va_extra_joins) . "\n\t\t\t\t\t" . (sizeof($va_sql_wheres) ? 'WHERE ' : '') . "\n\t\t\t\t\t" . join(' AND ', $va_sql_wheres) . "\n\t\t\t\t\tORDER BY csl.name\n\t\t\t\t", $va_sql_params);
             $t_list = new ca_lists();
             $va_sets = array();
             while ($qr_res->nextRow()) {
                 $vn_table_num = $qr_res->get('table_num');
                 if (!isset($va_type_name_cache[$vn_table_num]) || !($vs_set_type = $va_type_name_cache[$vn_table_num])) {
                     $vs_set_type = $va_type_name_cache[$vn_table_num] = $this->getSetContentTypeName($vn_table_num, array('number' => 'plural'));
                 }
                 $vs_type = $t_list->getItemFromListForDisplayByItemID('set_types', $qr_res->get('type_id'));
                 $va_sets[$qr_res->get('set_id')][$qr_res->get('locale_id')] = array_merge($qr_res->getRow(), array('item_count' => intval($va_item_counts[$qr_res->get('set_id')]), 'set_content_type' => $vs_set_type, 'set_type' => $vs_type));
             }
             return $va_sets;
         }
     }
 }
 /**
  * Find row(s) with fields having values matching specific values. 
  * Results can be returned as model instances, numeric ids or search results (when possible).
  *
  * Exact matching is performed using values in $pa_values. Partial and pattern matching are not supported. Searches may include
  * multiple fields with boolean AND and OR. For example, you can find ca_objects rows with idno = 2012.001 and access = 1 by passing the
  * "boolean" option as "AND" and $pa_values set to array("idno" => "2012.001", "access" => 1).
  * You could find all rows with either the idno or the access values by setting "boolean" to "OR"
  *
  * Keys in the $pa_values parameters must be valid fields in the table which the model sub-class represents. You may also search on preferred and
  * non-preferred labels by specified keys and values for label table fields in "preferred_labels" and "nonpreferred_labels" sub-arrays. For example:
  *
  * array("idno" => 2012.001", "access" => 1, "preferred_labels" => array("name" => "Luna Park at Night"))
  *
  * will find rows with the idno, access and preferred label values.
  *
  * LabelableBaseModelWithAttributes::find() is not a replacement for the SearchEngine. It is intended as a quick and convenient way to programatically fetch rows using
  * simple, clear cut criteria. If you need to fetch rows based upon an identifer or status value LabelableBaseModelWithAttributes::find() will be quicker and less code than
  * using the SearchEngine. For full-text searches, searches on attributes, or searches that require transformations or complex boolean operations use
  * the SearchEngine.
  *
  * @param array $pa_values An array of values to match. Keys are field names, metadata element codes or preferred_labels and /or nonpreferred_labels. This must be an array with at least one key-value pair where the key is a valid field name for the model.
  * @param array $pa_options Options are:
  *		transaction = optional Transaction instance. If set then all database access is done within the context of the transaction
  *		returnAs = what to return; possible values are:
  *			searchResult			= a search result instance (aka. a subclass of BaseSearchResult), when the calling subclass is searchable (ie. <classname>Search and <classname>SearchResult classes are defined) 
  *			ids						= an array of ids (aka. primary keys)
  *			modelInstances			= an array of instances, one for each match. Each instance is the same class as the caller, a subclass of BaseModel 
  *			firstId					= the id (primary key) of the first match. This is the same as the first item in the array returned by 'ids'
  *			firstModelInstance		= the instance of the first match. This is the same as the first instance in the array returned by 'modelInstances'
  *			count					= the number of matches
  *		
  *			The default is ids
  *	
  *		limit = if searchResult, ids or modelInstances is set, limits number of returned matches. Default is no limit
  *		boolean = determines how multiple field values in $pa_values are combined to produce the final result. Possible values are:
  *			AND						= find rows that match all criteria in $pa_values
  *			OR						= find rows that match any criteria in $pa_values
  *
  *			The default is AND
  *
  *		labelBoolean = determines how multiple field values in $pa_values['preferred_labels'] and $pa_values['nonpreferred_labels'] are combined to produce the final result. Possible values are:
  *			AND						= find rows that match all criteria in $pa_values['preferred_labels']/$pa_values['nonpreferred_labels']
  *			OR						= find rows that match any criteria in $pa_values['preferred_labels']/$pa_values['nonpreferred_labels']
  *
  *			The default is AND
  *
  *		sort = field to sort on. Must be in <table>.<field> format and be an intrinsic field in either the primary table or the label table. Sort order can be set using the sortDirection option.
  *		sortDirection = the direction of the sort. Values are ASC (ascending) and DESC (descending). [Default is ASC]
  *		allowWildcards = consider "%" as a wildcard when searching. Any term including a "%" character will be queried using the SQL LIKE operator. [Default is false]
  *
  * @return mixed Depending upon the returnAs option setting, an array, subclass of LabelableBaseModelWithAttributes or integer may be returned.
  */
 public static function find($pa_values, $pa_options = null)
 {
     if (!is_array($pa_values) || sizeof($pa_values) == 0) {
         return null;
     }
     $ps_return_as = caGetOption('returnAs', $pa_options, 'ids', array('forceLowercase' => true, 'validValues' => array('searchResult', 'ids', 'modelInstances', 'firstId', 'firstModelInstance', 'count')));
     $ps_boolean = caGetOption('boolean', $pa_options, 'and', array('forceLowercase' => true, 'validValues' => array('and', 'or')));
     $ps_label_boolean = caGetOption('labelBoolean', $pa_options, 'and', array('forceLowercase' => true, 'validValues' => array('and', 'or')));
     $ps_sort = caGetOption('sort', $pa_options, null);
     $vs_table = get_called_class();
     $t_instance = new $vs_table();
     $vn_table_num = $t_instance->tableNum();
     $vs_table_pk = $t_instance->primaryKey();
     $t_label = $t_instance->getLabelTableInstance();
     $vs_label_table = $t_label->tableName();
     $vs_label_table_pk = $t_label->primaryKey();
     $vb_has_simple_fields = false;
     foreach ($pa_values as $vs_field => $vm_value) {
         if (!is_array($vm_value) && $t_instance->hasField($vs_field)) {
             $vb_has_simple_fields = true;
             break;
         }
     }
     $vb_has_label_fields = false;
     foreach ($pa_values as $vs_field => $vm_value) {
         if (in_array($vs_field, array('preferred_labels', 'nonpreferred_labels')) && is_array($vm_value) && sizeof($vm_value)) {
             $vb_has_label_fields = true;
             break;
         }
     }
     $vs_sort_proc = $ps_sort;
     if (preg_match("!^{$vs_table}.preferred_labels[\\.]{0,1}(.*)!", $ps_sort, $va_matches) || preg_match("!^{$vs_table}.nonpreferred_labels[\\.]{0,1}(.*)!", $ps_sort, $va_matches)) {
         $vs_sort_proc = $va_matches[1] && $t_label->hasField($va_matches[1]) ? "{$vs_label_table}." . $va_matches[1] : "{$vs_label_table}." . $t_label->getDisplayField();
         $vb_has_label_fields = true;
     }
     $vb_has_attributes = false;
     $va_element_codes = $t_instance->getApplicableElementCodes(null, true, false);
     foreach ($pa_values as $vs_field => $vm_value) {
         if (!is_array($vm_value) && in_array($vs_field, $va_element_codes)) {
             $vb_has_attributes = true;
             break;
         }
     }
     $va_joins = array();
     $va_sql_params = array();
     if ($vb_has_simple_fields) {
         //
         // Convert type id
         //
         if ($t_instance->ATTRIBUTE_TYPE_LIST_CODE) {
             if (isset($pa_values[$t_instance->ATTRIBUTE_TYPE_ID_FLD]) && !is_numeric($pa_values[$t_instance->ATTRIBUTE_TYPE_ID_FLD])) {
                 if (!is_array($pa_values[$t_instance->ATTRIBUTE_TYPE_ID_FLD])) {
                     $pa_values[$t_instance->ATTRIBUTE_TYPE_ID_FLD] = array($pa_values[$t_instance->ATTRIBUTE_TYPE_ID_FLD]);
                 }
                 foreach ($pa_values[$t_instance->ATTRIBUTE_TYPE_ID_FLD] as $vn_i => $vm_value) {
                     if (!is_numeric($vm_value)) {
                         if ($vn_id = ca_lists::getItemID($t_instance->ATTRIBUTE_TYPE_LIST_CODE, $vm_value)) {
                             $pa_values[$t_instance->ATTRIBUTE_TYPE_ID_FLD][$vn_i] = $vn_id;
                         }
                     }
                 }
             }
         }
         //
         // Convert other intrinsic list references
         //
         foreach ($pa_values as $vs_field => $vm_value) {
             if ($vs_field == $t_instance->ATTRIBUTE_TYPE_ID_FLD) {
                 continue;
             }
             if ($vs_list_code = $t_instance->getFieldInfo($vs_field, 'LIST_CODE')) {
                 if (!is_array($vm_value)) {
                     $pa_values[$vs_field] = $vm_value = array($vm_value);
                 }
                 foreach ($vm_value as $vn_i => $vm_ivalue) {
                     if (is_numeric($vm_ivalue)) {
                         continue;
                     }
                     if ($vn_id = ca_lists::getItemID($vs_list_code, $vm_ivalue)) {
                         $pa_values[$vs_field][$vn_i] = $vn_id;
                     }
                 }
             }
         }
     }
     $va_sql_wheres = array();
     if ($vb_has_simple_fields && !$vb_has_attributes && !$vb_has_label_fields) {
         return parent::find($pa_values, $pa_options);
     }
     $va_label_sql = array();
     if ($vb_has_label_fields) {
         $va_joins[] = " INNER JOIN {$vs_label_table} ON {$vs_label_table}.{$vs_table_pk} = {$vs_table}.{$vs_table_pk} ";
         if (isset($pa_values['preferred_labels']) && is_array($pa_values['preferred_labels'])) {
             $va_sql_wheres[] = "({$vs_label_table}.is_preferred = 1)";
             foreach ($pa_values['preferred_labels'] as $vs_field => $vm_value) {
                 if (!$t_label->hasField($vs_field)) {
                     return false;
                 }
                 if ($t_label->_getFieldTypeType($vs_field) == 0) {
                     if (!is_numeric($vm_value) && !is_null($vm_value)) {
                         $vm_value = intval($vm_value);
                     }
                 } else {
                     $vm_value = $t_label->quote($vs_field, is_null($vm_value) ? '' : $vm_value);
                 }
                 if (is_null($vm_value)) {
                     $va_sql_wheres[] = "({$vs_label_table}.{$vs_field} IS NULL)";
                 } elseif (caGetOption('allowWildcards', $pa_options, false) && strpos($vm_value, '%') !== false) {
                     $va_sql_wheres[] = "({$vs_label_table}.{$vs_field} LIKE {$vm_value})";
                 } else {
                     if ($vm_value === '') {
                         continue;
                     }
                     $va_sql_wheres[] = "({$vs_label_table}.{$vs_field} = {$vm_value})";
                 }
             }
             $va_label_sql[] = "(" . join(" {$ps_label_boolean} ", $va_sql_wheres) . ")";
             $va_sql_wheres = array();
         }
         if (isset($pa_values['nonpreferred_labels']) && is_array($pa_values['nonpreferred_labels'])) {
             $va_sql_wheres[] = "({$vs_label_table}.is_preferred = 0)";
             foreach ($pa_values['nonpreferred_labels'] as $vs_field => $vm_value) {
                 if (!$t_label->hasField($vs_field)) {
                     return false;
                 }
                 if ($t_label->_getFieldTypeType($vs_field) == 0) {
                     if (!is_numeric($vm_value) && !is_null($vm_value)) {
                         $vm_value = intval($vm_value);
                     }
                 } else {
                     $vm_value = $t_label->quote($vs_field, is_null($vm_value) ? '' : $vm_value);
                 }
                 if (is_null($vm_value)) {
                     $va_sql_wheres[] = "({$vs_label_table}.{$vs_field} IS NULL)";
                 } else {
                     if ($vm_value === '') {
                         continue;
                     }
                     $va_sql_wheres[] = "({$vs_label_table}.{$vs_field} = {$vm_value})";
                 }
             }
             $va_label_sql[] = "(" . join(" {$ps_label_boolean} ", $va_sql_wheres) . ")";
             $va_sql_wheres = array();
         }
     }
     if ($vb_has_simple_fields) {
         foreach ($pa_values as $vs_field => $vm_value) {
             //if (is_array($vm_value)) { continue; }
             if (!$t_instance->hasField($vs_field)) {
                 continue;
             }
             if ($t_instance->_getFieldTypeType($vs_field) == 0) {
                 if (!is_numeric($vm_value) && !is_null($vm_value)) {
                     if (is_array($vm_value)) {
                         foreach ($vm_value as $vn_i => $vm_ivalue) {
                             $vm_value[$vn_i] = intval($vm_ivalue);
                         }
                     } else {
                         $vm_value = intval($vm_value);
                     }
                 }
             }
             if (is_null($vm_value)) {
                 $va_label_sql[] = "({$vs_table}.{$vs_field} IS NULL)";
             } elseif (caGetOption('allowWildcards', $pa_options, false) && strpos($vm_value, '%') !== false) {
                 $va_label_sql[] = "({$vs_table}.{$vs_field} LIKE ?)";
                 $va_sql_params[] = $vm_value;
             } else {
                 if ($vm_value === '') {
                     continue;
                 }
                 if (is_array($vm_value)) {
                     if (!sizeof($vm_value)) {
                         continue;
                     }
                     $va_label_sql[] = "({$vs_table}.{$vs_field} IN (?))";
                 } else {
                     $va_label_sql[] = "({$vs_table}.{$vs_field} = ?)";
                 }
                 $va_sql_params[] = $vm_value;
             }
         }
     }
     if ($vb_has_attributes) {
         $va_joins[] = " INNER JOIN ca_attributes ON ca_attributes.row_id = {$vs_table}.{$vs_table_pk} AND ca_attributes.table_num = {$vn_table_num} ";
         $va_joins[] = " INNER JOIN ca_attribute_values ON ca_attribute_values.attribute_id = ca_attributes.attribute_id ";
         foreach ($pa_values as $vs_field => $vm_value) {
             if (($vn_element_id = array_search($vs_field, $va_element_codes)) !== false) {
                 $vs_q = " (ca_attribute_values.element_id = {$vn_element_id}) AND  ";
                 switch ($vn_datatype = $t_instance->_getElementDatatype($vs_field)) {
                     case 0:
                         // continue
                     // continue
                     case 15:
                         // media
                     // media
                     case 16:
                         // file
                         // SKIP
                         continue 2;
                         break;
                     case 2:
                         // date
                         if (is_array($va_date = caDateToHistoricTimestamps($vm_value))) {
                             $vs_q .= "((ca_attribute_values.value_decimal1 BETWEEN ? AND ?) OR (ca_attribute_values.value_decimal2 BETWEEN ? AND ?))";
                             array_push($va_sql_params, $va_date['start'], $va_date['end'], $va_date['start'], $va_date['end']);
                         } else {
                             continue 2;
                         }
                         break;
                     case 3:
                         // list
                         $vn_item_id = is_numeric($vm_value) ? (int) $vm_value : (int) caGetListItemID($vm_value);
                         $vs_q .= "(ca_attribute_values.item_id = ?)";
                         $va_sql_params[] = $vn_item_id;
                         break;
                     default:
                         if (!($vs_fld = Attribute::getSortFieldForDatatype($vn_datatype))) {
                             $vs_fld = 'value_longtext1';
                         }
                         if (caGetOption('allowWildcards', $pa_options, false) && strpos($vm_value, '%') !== false) {
                             $vs_q .= "(ca_attribute_values.{$vs_fld} LIKE ?)";
                         } else {
                             $vs_q .= "(ca_attribute_values.{$vs_fld} = ?)";
                         }
                         $va_sql_params[] = (string) $vm_value;
                         break;
                 }
                 $va_label_sql[] = "({$vs_q})";
             }
         }
     }
     if (!sizeof($va_label_sql)) {
         return null;
     }
     $vs_deleted_sql = $t_instance->hasField('deleted') ? "({$vs_table}.deleted = 0) AND " : '';
     $vs_sql = "SELECT * FROM {$vs_table}";
     $vs_sql .= join("\n", $va_joins);
     $vs_sql .= " WHERE {$vs_deleted_sql} " . join(" {$ps_boolean} ", $va_label_sql);
     $vs_orderby = '';
     if ($vs_sort_proc) {
         $vs_sort_direction = caGetOption('sortDirection', $pa_options, 'ASC', array('validValues' => array('ASC', 'DESC')));
         $va_tmp = explode(".", $vs_sort_proc);
         if (sizeof($va_tmp) == 2) {
             switch ($va_tmp[0]) {
                 case $vs_table:
                     if ($t_instance->hasField($va_tmp[1])) {
                         $vs_orderby = " ORDER BY {$vs_sort_proc} {$vs_sort_direction}";
                     }
                     break;
                 case $vs_label_table:
                     if ($t_label->hasField($va_tmp[1])) {
                         $vs_orderby = " ORDER BY {$vs_sort_proc} {$vs_sort_direction}";
                     }
                     break;
             }
         }
         if ($vs_orderby) {
             $vs_sql .= $vs_orderby;
         }
     }
     if (isset($pa_options['transaction']) && $pa_options['transaction'] instanceof Transaction) {
         $o_db = $pa_options['transaction']->getDb();
     } else {
         $o_db = new Db();
     }
     $vn_limit = isset($pa_options['limit']) && (int) $pa_options['limit'] > 0 ? (int) $pa_options['limit'] : null;
     $qr_res = $o_db->query($vs_sql, $va_sql_params);
     $vn_c = 0;
     $vs_pk = $t_instance->primaryKey();
     switch ($ps_return_as) {
         case 'firstmodelinstance':
             while ($qr_res->nextRow()) {
                 $o_instance = new $vs_table();
                 if ($o_instance->load($qr_res->get($vs_pk))) {
                     return $o_instance;
                 }
             }
             return null;
             break;
         case 'modelinstances':
             $va_instances = array();
             while ($qr_res->nextRow()) {
                 $o_instance = new $vs_table();
                 if ($o_instance->load($qr_res->get($vs_pk))) {
                     $va_instances[] = $o_instance;
                     $vn_c++;
                     if ($vn_limit && $vn_c >= $vn_limit) {
                         break;
                     }
                 }
             }
             return $va_instances;
             break;
         case 'firstid':
             if ($qr_res->nextRow()) {
                 return $qr_res->get($vs_pk);
             }
             return null;
             break;
         case 'count':
             return $qr_res->numRows();
             break;
         default:
         case 'ids':
         case 'searchresult':
             $va_ids = array();
             while ($qr_res->nextRow()) {
                 $va_ids[] = $qr_res->get($vs_pk);
                 $vn_c++;
                 if ($vn_limit && $vn_c >= $vn_limit) {
                     break;
                 }
             }
             if ($ps_return_as == 'searchresult') {
                 if (sizeof($va_ids) > 0) {
                     return $t_instance->makeSearchResult($t_instance->tableName(), $va_ids);
                 }
                 return null;
             } else {
                 return $va_ids;
             }
             break;
     }
 }
 /**
  * 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 (!$this->hasField($va_tmp[sizeof($va_tmp) - 1]) || $this->getFieldInfo($va_tmp[sizeof($va_tmp) - 1], 'ALLOW_BUNDLE_ACCESS_CHECK')) {
         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;
                         }
                         return join($vs_delimiter, $va_text);
                     }
                 }
                 $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));
                 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;
 }
示例#18
0
    if ($t_item->get('ca_entities.preferred_labels', array('restrictToRelationshipTypes' => array('artist')))) {
        print $t_item->get('ca_entities.preferred_labels', array('restrictToRelationshipTypes' => array('artist'))) . "<br/>";
    }
    print "<em>" . $t_item->get('ca_objects.preferred_labels') . "</em> (" . $t_item->get('ca_objects.idno') . ")<br/><br/>";
    $vn_movement_type_id = caGetListItemID('movement_types', 'movement');
    $vn_condition_type_id = caGetListItemID('movement_types', 'condition');
    $vs_movement_for_display = caGetListItemForDisplay('movement_types', 'movement');
    $vs_condition_for_display = caGetListItemForDisplay('movement_types', 'condition');
    print "<strong>Launch new</strong>:<br/>";
    print caEditorLink($this->request, "&nbsp;&nbsp;{$vs_movement_for_display}", '', 'ca_movements', null, array('type_id' => $vn_movement_type_id, 'rel' => 1, 'rel_table' => 'ca_objects', 'rel_type_id' => 'part', 'rel_id' => $t_item->getPrimaryKey()));
    print "</br >";
    print caEditorLink($this->request, "&nbsp;&nbsp;{$vs_condition_for_display}", '', 'ca_movements', null, array('type_id' => $vn_condition_type_id, 'rel' => 1, 'rel_table' => 'ca_objects', 'rel_type_id' => 'part', 'rel_id' => $t_item->getPrimaryKey()));
}
/**
 * UMMA additions to exhibit inspector
 */
if ($t_item->tableName() === 'ca_occurrences' && $t_item->get('type_id') == caGetListItemID('occurrence_types', 'exhibition')) {
    $vn_loan_object_type_id = caGetListItemID('loan_types', 'loan_object');
    $vs_loan_object_for_display = caGetListItemForDisplay('loan_types', 'loan_object');
    print caEditorLink($this->request, "Launch new {$vs_loan_object_for_display}", '', 'ca_loans', null, array('type_id' => $vn_loan_object_type_id, 'rel' => 1, 'rel_table' => 'ca_occurrences', 'rel_type_id' => 'related', 'rel_id' => $t_item->getPrimaryKey()));
}
/**
 * UMMA additions to loan inspector
 */
if ($t_item->tableName() === 'ca_loans' && $t_item->get('type_id') == caGetListItemID('loan_types', 'loan_in')) {
    $vn_loan_object_type_id = caGetListItemID('loan_types', 'loan_object');
    $vs_loan_object_for_display = caGetListItemForDisplay('loan_types', 'loan_object');
    print caEditorLink($this->request, "Launch new {$vs_loan_object_for_display}", '', 'ca_loans', null, array('type_id' => $vn_loan_object_type_id, 'rel' => 1, 'rel_table' => 'ca_loans', 'rel_type_id' => 'related', 'rel_id' => $t_item->getPrimaryKey()));
}
?>
	</div>