コード例 #1
0
 /**
  * Overrides get() to support bundleable-level fields (relationships)
  *
  * Options:
  *		All supported by BaseModelWithAttributes::get() plus:
  *		retrictToRelationshipTypes - array of ca_relationship_types.type_id values to filter related items on. *MUST BE INTEGER TYPE_IDs, NOT type_code's* This limitation is for performance reasons. You have to convert codes to integer type_id's before invoking get
  *		sort = optional array of bundles to sort returned values on. Currently only supported when getting related values via simple related <table_name> and <table_name>.related invokations. Eg. from a ca_objects results you can use the 'sort' option got get('ca_entities'), get('ca_entities.related') or get('ca_objects.related'). The bundle specifiers are fields with or without tablename. Only those fields returned for the related tables (intrinsics and label fields) are sortable. You cannot sort on attributes.
  *		returnAsLink = if true and $ps_field is set to a specific field in a related table, or $ps_field is set to a related table (eg. ca_entities or ca_entities.related) AND the template option is set and returnAllLocales is not set, then returned values will be links. The destination of the link will be the appropriate editor when executed within Providence or the appropriate detail page when executed within Pawtucket or another front-end. Default is false.
  *		returnAsLinkText = text to use a content of HTML link. If omitted the url itself is used as the link content.
  *		returnAsLinkAttributes = array of attributes to include in link <a> tag. Use this to set class, alt and any other link attributes.
  *		returnAsLinkTarget = Optional link target. If any plugin implementing hookGetAsLink() responds to the specified target then the plugin will be used to generate the links rather than CA's default link generator.
  *		filter = optional array of elements to filter returned values on. The element must be part off the container being fetched from. For example, if you're get()'ing a value from a container element (Eg. ca_objects.dates.date_value) you can filter on any other subelement in that container by passing the name of the subelement and a value (Eg. "date_type" => "copyright"). Pass only the name of the subelement, not the full path that includes the table and container element. You can filter on multiple subelements by passing each subelement as a key in the array. Only values that match all filters are returned. You can filter on multiple values for a subelement by passing an array of values rather than a scalar (Eg. "date_type" => array("copyright", "patent")). Values that match *any* of the values will be returned. Only simple equivalance is supported. NOTE: Filters are only available when returnAsArray is set. They will be ignored if returnAsArray is not set.
  */
 public function get($ps_field, $pa_options = null)
 {
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     $vs_template = caGetOption('template', $pa_options, null);
     $vb_return_as_array = caGetOption('returnAsArray', $pa_options, false, array('castTo' => 'bool'));
     $vb_return_as_link = caGetOption('returnAsLink', $pa_options, false, array('castTo' => 'bool'));
     $vs_return_as_link_text = caGetOption('returnAsLinkText', $pa_options, '');
     $vs_return_as_link_target = caGetOption('returnAsLinkTarget', $pa_options, '');
     $va_return_as_link_attributes = caGetOption('returnAsLinkAttributes', $pa_options, array(), array('castTo' => 'array'));
     $vb_return_all_locales = caGetOption('returnAllLocales', $pa_options, false, array('castTo' => 'bool'));
     $vs_delimiter = caGetOption('delimiter', $pa_options, '');
     $va_restrict_to_rel_types = caGetOption('restrictToRelationshipTypes', $pa_options, null);
     $va_filters = caGetOption('filters', $pa_options, array(), array('castTo' => 'array'));
     if ($vb_return_all_locales && !$vb_return_as_array) {
         $vb_return_as_array = true;
     }
     $va_return_values = null;
     // does get refer to an attribute?
     $va_tmp = explode('.', $ps_field);
     if (sizeof($va_tmp) > 1) {
         if ($va_tmp[0] != $this->tableName()) {
             $vs_access_chk_key = $ps_field;
         } else {
             $va_tmp2 = $va_tmp;
             array_shift($va_tmp2);
             $vs_access_chk_key = join(".", $va_tmp2);
         }
     } else {
         $vs_access_chk_key = $ps_field;
     }
     if ($va_tmp[sizeof($va_tmp) - 1] != 'access' && (!$this->hasField($va_tmp[sizeof($va_tmp) - 1]) || $this->getFieldInfo($va_tmp[sizeof($va_tmp) - 1], 'ALLOW_BUNDLE_ACCESS_CHECK'))) {
         // Always allow "access" value to be gotten otherwise none of the Pawtucket access checks will work.
         if (caGetBundleAccessLevel($this->tableName(), $vs_access_chk_key) == __CA_BUNDLE_ACCESS_NONE__) {
             return null;
         }
     }
     switch (sizeof($va_tmp)) {
         # -------------------------------------
         case 1:
             // table_name
             if ($t_instance = $this->_DATAMODEL->getInstanceByTableName($va_tmp[0], true)) {
                 $vs_pk = $t_instance->primaryKey();
                 $va_related_items = $this->getRelatedItems($va_tmp[0], $pa_options);
                 if (!is_array($va_related_items)) {
                     return null;
                 }
                 if (!$vs_template && !$vb_return_all_locales && !$vb_return_as_array) {
                     $vs_template = "^preferred_labels";
                 }
                 if ($vb_return_all_locales) {
                     $va_related_tmp = array();
                     foreach ($va_related_items as $vn_i => $va_related_item) {
                         $va_related_tmp[$vn_i][$va_related_item['locale_id']] = $va_related_item;
                     }
                     $va_related_items = $va_related_tmp;
                 } else {
                     if ($vs_template) {
                         $va_template_opts = $pa_options;
                         unset($va_template_opts['request']);
                         unset($va_template_opts['template']);
                         $va_template_opts['returnAsLink'] = false;
                         $va_template_opts['returnAsArray'] = true;
                         $va_template_opts['requireLinkTags'] = true;
                         $va_ids = array();
                         if (is_array($va_rel_items = $this->get($va_tmp[0], $va_template_opts))) {
                             foreach ($va_rel_items as $vn_rel_id => $va_rel_item) {
                                 $va_ids[] = $va_rel_item[$vs_pk];
                                 $va_template_opts['relationshipValues'][$va_rel_item[$vs_pk]][$va_rel_item['relation_id']]['relationship_typename'] = $va_rel_item['relationship_typename'];
                                 $va_template_opts['relationshipValues'][$va_rel_item[$vs_pk]][$va_rel_item['relation_id']]['relationship_type_id'] = $va_rel_item['relationship_type_id'];
                                 $va_template_opts['relationshipValues'][$va_rel_item[$vs_pk]][$va_rel_item['relation_id']]['label'] = $va_rel_item['label'];
                             }
                         } else {
                             $va_rel_items = array();
                         }
                         $va_text = caProcessTemplateForIDs($vs_template, $va_tmp[0], $va_ids, $va_template_opts);
                         if ($vb_return_as_link) {
                             $va_text = caCreateLinksFromText($va_text, $va_tmp[0], $va_ids, $vs_return_as_link_class, $vs_return_as_link_target);
                         }
                         if ($vb_return_as_array) {
                             $va_return_values = $va_text;
                         }
                         if (is_array($va_text)) {
                             return join($vs_delimiter, $va_text);
                         } else {
                             return null;
                         }
                     }
                 }
                 $va_return_values = $va_related_items;
             }
             break;
             # -------------------------------------
         # -------------------------------------
         case 2:
             // table_name.field_name || table_name.related
         // table_name.field_name || table_name.related
         case 3:
             // table_name.field_name.sub_element || table_name.related.field_name
         // table_name.field_name.sub_element || table_name.related.field_name
         case 4:
             // table_name.related.field_name.sub_element
             //
             // TODO: this code is compact, relatively simple and works but is slow since it
             // generates a lot more identical database queries than we'd like
             // We will need to add some notion of caching so that multiple calls to get()
             // for various fields in the same list of related items don't cause repeated queries
             //
             $vb_is_related = false;
             $vb_is_hierarchy = false;
             if ($va_tmp[1] === 'related') {
                 array_splice($va_tmp, 1, 1);
                 $vb_is_related = true;
             }
             if ($vb_is_related || $va_tmp[0] !== $this->tableName()) {
                 // must be related table
                 if (!($t_instance = $this->_DATAMODEL->getInstanceByTableName($va_tmp[0], true))) {
                     return null;
                 }
                 $vs_pk = $t_instance->primaryKey();
                 if ($vs_template && !$vb_return_all_locales) {
                     $va_template_opts = $pa_options;
                     unset($va_template_opts['request']);
                     unset($va_template_opts['template']);
                     $va_template_opts['returnAsLink'] = false;
                     $va_template_opts['returnAsArray'] = true;
                     $va_template_opts['requireLinkTags'] = true;
                     $va_ids = array();
                     if (is_array($va_rel_items = $this->get($va_tmp[0], $va_template_opts))) {
                         foreach ($va_rel_items as $vn_rel_id => $va_rel_item) {
                             $va_ids[] = $va_rel_item[$vs_pk];
                             $va_template_opts['relationshipValues'][$va_rel_item[$vs_pk]][$va_rel_item['relation_id']]['relationship_typename'] = $va_rel_item['relationship_typename'];
                         }
                     } else {
                         $va_rel_items = array();
                     }
                     $va_text = caProcessTemplateForIDs($vs_template, $va_tmp[0], $va_ids, $va_template_opts);
                     if ($vb_return_as_link) {
                         $va_text = caCreateLinksFromText($va_text, $va_tmp[0], $va_ids, $vs_return_as_link_class, $vs_return_as_link_target);
                     }
                     if ($vb_return_as_array) {
                         $va_return_values = $va_text;
                     }
                     return join($vs_delimiter, $va_text);
                 }
                 $va_related_items = $this->getRelatedItems($va_tmp[0], array_merge($pa_options, array('returnLabelsAsArray' => true)));
                 if (is_array($va_restrict_to_rel_types) && sizeof($va_restrict_to_rel_types)) {
                     require_once __CA_MODELS_DIR__ . '/ca_relationship_types.php';
                     $t_rel_types = new ca_relationship_types();
                     $va_restrict_to_rel_types = $t_rel_types->relationshipTypeListToIDs($t_rel_types->getRelationshipTypeTable($this->tableName(), $va_tmp[0]), $va_restrict_to_rel_types, array('includeChildren' => true));
                 }
                 $vb_field_is_specified = sizeof($va_tmp) == 2 && (!$vb_is_hierarchy && $va_tmp[1] != 'related') || sizeof($va_tmp) >= 3;
                 $va_ids = array();
                 $va_items = array();
                 if (is_array($va_related_items) && sizeof($va_related_items) > 0) {
                     foreach ($va_related_items as $vn_rel_id => $va_related_item) {
                         $va_ids[] = $va_related_item[$vs_pk];
                         if (is_array($va_restrict_to_rel_types) && !in_array($va_related_item['relationship_type_id'], $va_restrict_to_rel_types)) {
                             continue;
                         }
                         if ($va_tmp[1] == 'relationship_typename') {
                             $va_items[] = $va_related_item['relationship_typename'];
                             continue;
                         }
                         if ($va_tmp[1] == 'hierarchy') {
                             $vb_is_hierarchy = true;
                             if ($t_instance->load($va_related_item[$t_instance->primaryKey()])) {
                                 $va_items[] = $t_instance->get(join('.', $va_tmp), $pa_options);
                             }
                             continue;
                         }
                         // is field directly returned by getRelatedItems()?
                         if (isset($va_tmp[1]) && isset($va_related_item[$va_tmp[1]]) && $t_instance->hasField($va_tmp[1])) {
                             if ($vb_return_as_array) {
                                 if ($vb_return_all_locales) {
                                     // for return as locale-index array
                                     $va_items[$va_related_item['relation_id']][$va_related_item['locale_id']][] = $va_related_item[$va_tmp[1]];
                                 } else {
                                     // for return as simple array
                                     $va_items[] = $va_related_item[$va_tmp[1]];
                                 }
                             } else {
                                 // for return as string
                                 $va_items[] = $va_related_item[$va_tmp[1]];
                             }
                             continue;
                         }
                         // is field preferred labels?
                         if ($va_tmp[1] === 'preferred_labels') {
                             if (!isset($va_tmp[2])) {
                                 if ($vb_return_as_array || $vb_return_all_locales) {
                                     if ($vb_return_all_locales) {
                                         // for return as locale-index array
                                         $va_items[$va_related_item['relation_id']][] = $va_related_item['labels'];
                                     } else {
                                         // for return as simple array
                                         $va_item_list = caExtractValuesByUserLocale(array($va_related_item['labels']));
                                         foreach ($va_item_list as $vn_x => $va_item) {
                                             $va_items[] = $va_item[$t_instance->getLabelDisplayField()];
                                         }
                                     }
                                 } else {
                                     // for return as string
                                     $va_items[] = $va_related_item['label'][$t_instance->getLabelDisplayField()];
                                 }
                             } else {
                                 if ($vb_return_all_locales) {
                                     // for return as locale-index array
                                     foreach ($va_related_item['labels'] as $vn_locale_id => $va_label) {
                                         $va_items[$va_related_item['relation_id']][$vn_locale_id][] = $va_label[$va_tmp[2]];
                                     }
                                 } else {
                                     foreach (caExtractValuesByUserLocale(array($va_related_item['labels'])) as $vn_i => $va_label) {
                                         // for return as string or simple array
                                         $va_items[] = $va_label[$va_tmp[2]];
                                     }
                                 }
                             }
                             continue;
                         }
                         // TODO: add support for nonpreferred labels
                         // Get related attributes
                         if ($t_instance->load($va_related_item[$t_instance->primaryKey()])) {
                             if (isset($va_tmp[1])) {
                                 if ($vm_val = $t_instance->get(join(".", $va_tmp), $pa_options)) {
                                     if ($vb_return_as_link && !$vb_return_as_array && !$vb_return_all_locales) {
                                         $va_items[] = $vm_val;
                                     } else {
                                         $va_items[] = $vm_val;
                                         //break;
                                     }
                                 }
                             } else {
                                 $va_items[] = $this->get($va_tmp[0], $pa_options);
                             }
                         } else {
                             $va_items[] = null;
                         }
                     }
                 }
                 if ($vb_return_as_link && !$vb_return_all_locales) {
                     $va_items = caCreateLinksFromText($va_items, $va_tmp[0], $va_ids, $vs_return_as_link_class, $vs_return_as_link_target);
                 }
                 if ($vb_return_as_array) {
                     $va_return_values = $va_items;
                 } else {
                     return join($vs_delimiter, $va_items);
                 }
             }
             break;
             # -------------------------------------
     }
     if (!$va_return_values) {
         $va_return_values = parent::get($ps_field, $pa_options);
     }
     //
     // Perform filtering
     //
     if ($vb_return_as_array && sizeof($va_filters)) {
         $va_tmp = explode(".", $ps_field);
         if (sizeof($va_tmp) > 1) {
             array_pop($va_tmp);
         }
         if ($t_instance = $this->getAppDataModel()->getInstanceByTableName($va_tmp[0], true)) {
             $va_keepers = array();
             foreach ($va_filters as $vs_filter => $va_filter_vals) {
                 if (!is_array($va_filter_vals)) {
                     $va_filter_vals = array($va_filter_vals);
                 }
                 foreach ($va_filter_vals as $vn_index => $vs_filter_val) {
                     // is value a list attribute idno?
                     if (!is_numeric($vs_filter_val) && (($t_element = $t_instance->_getElementInstance($vs_filter)) && $t_element->get('datatype') == 3)) {
                         $va_filter_vals[$vn_index] = caGetListItemID($t_element->get('list_id'), $vs_filter_val);
                     }
                 }
                 $va_filter_values = $this->get(join(".", $va_tmp) . ".{$vs_filter}", array('returnAsArray' => true));
                 if (!is_array($va_filter_values)) {
                     $va_filter_values = array();
                 }
                 foreach ($va_filter_values as $vn_id => $vm_filtered_val) {
                     if ((!isset($va_keepers[$vn_id]) || $va_keepers[$vn_id]) && in_array($vm_filtered_val, $va_filter_vals)) {
                         // any match for the element counts
                         $va_keepers[$vn_id] = true;
                     } else {
                         // if no match on any criteria kill it
                         $va_keepers[$vn_id] = false;
                     }
                 }
             }
             $va_filtered_vals = array();
             foreach ($va_keepers as $vn_id => $vb_include) {
                 if (!$vb_include) {
                     continue;
                 }
                 $va_filtered_vals[$vn_id] = $va_return_values[$vn_id];
             }
             return $va_filtered_vals;
         }
     }
     return $va_return_values;
 }
コード例 #2
0
/**
 * Converts the given list of relationship type names or relationship type_ids into an expanded list of numeric type_ids suitable for enforcing relationship type restrictions. Processing
 * includes expansion of types to include subtypes and conversion of any type codes to type_ids.
 *
 * @param mixed $pm_table_name_or_num Table name or number to which types apply
 * @param array $pa_types List of type codes and/or type_ids that are the basis of the list
 * @param array $pa_options Array of options:
 * 		dont_include_subtypes_in_type_restriction = if set, returned list is not expanded to include subtypes
 *		dontIncludeSubtypesInTypeRestriction = synonym for dont_include_subtypes_in_type_restriction
 *
 * @return array List of numeric type_ids
 */
function caMakeRelationshipTypeIDList($pm_table_name_or_num, $pa_types, $pa_options = null)
{
    $o_dm = Datamodel::load();
    if (isset($pa_options['dontIncludeSubtypesInTypeRestriction']) && (!isset($pa_options['dont_include_subtypes_in_type_restriction']) || !$pa_options['dont_include_subtypes_in_type_restriction'])) {
        $pa_options['dont_include_subtypes_in_type_restriction'] = $pa_options['dontIncludeSubtypesInTypeRestriction'];
    }
    $pa_options['includeChildren'] = isset($pa_options['dont_include_subtypes_in_type_restriction']) && $pa_options['dont_include_subtypes_in_type_restriction'] ? false : true;
    $t_rel_type = new ca_relationship_types();
    return $t_rel_type->relationshipTypeListToIDs($pm_table_name_or_num, $pa_types, $pa_options);
}
コード例 #3
0
 /**
  *
  */
 public static function _getRelativeIDsForRowIDs($ps_tablename, $ps_relative_to, $pa_row_ids, $ps_mode, $pa_options = null)
 {
     $o_dm = Datamodel::load();
     $t_instance = $o_dm->getInstanceByTableName($ps_tablename, true);
     if (!$t_instance) {
         return null;
     }
     $t_rel_instance = $o_dm->getInstanceByTableName($ps_relative_to, true);
     if (!$t_rel_instance) {
         return null;
     }
     $vs_pk = $t_instance->primaryKey();
     $vs_rel_pk = $t_rel_instance->primaryKey();
     $o_db = new Db();
     switch ($ps_mode) {
         case 'related':
             $va_params = array($pa_row_ids);
             if ($ps_tablename !== $ps_relative_to) {
                 // related
                 $vs_relationship_type_sql = null;
                 if (!is_array($va_path = array_keys($o_dm->getPath($ps_tablename, $ps_relative_to))) || !sizeof($va_path)) {
                     throw new Exception(_t("Cannot be path between %1 and %2", $ps_tablename, $ps_relative_to));
                 }
                 $va_joins = array();
                 switch (sizeof($va_path)) {
                     case 2:
                         $vs_left_table = $va_path[1];
                         $vs_right_table = $va_path[0];
                         $va_relationships = $o_dm->getRelationships($vs_left_table, $vs_right_table);
                         $va_conditions = array();
                         foreach ($va_relationships[$vs_left_table][$vs_right_table] as $va_rel) {
                             $va_conditions[] = "{$vs_left_table}.{$va_rel[0]} = {$vs_right_table}.{$va_rel[1]}";
                         }
                         $va_joins[] = "INNER JOIN {$vs_right_table} ON " . join(" OR ", $va_conditions);
                         break;
                     default:
                         $va_path = array_reverse($va_path);
                         $vs_left_table = array_shift($va_path);
                         foreach ($va_path as $vs_right_table) {
                             $va_relationships = $o_dm->getRelationships($vs_left_table, $vs_right_table);
                             $va_conditions = array();
                             foreach ($va_relationships[$vs_left_table][$vs_right_table] as $va_rel) {
                                 $va_conditions[] = "{$vs_left_table}.{$va_rel[0]} = {$vs_right_table}.{$va_rel[1]}";
                             }
                             $va_joins[] = "INNER JOIN {$vs_right_table} ON " . join(" OR ", $va_conditions);
                             $vs_left_table = $vs_right_table;
                         }
                         break;
                 }
                 $qr_res = $o_db->query("\n\t\t\t\t\t\tSELECT {$ps_relative_to}.{$vs_rel_pk} \n\t\t\t\t\t\tFROM {$ps_relative_to} \n\t\t\t\t\t\t" . join("\n", $va_joins) . "\n\t\t\t\t\t\tWHERE {$ps_tablename}.{$vs_pk} IN (?) {$vs_relationship_type_sql}\n\t\t\t\t\t", $va_params);
                 $va_vals = $qr_res->getAllFieldValues($vs_rel_pk);
                 if (!is_array($va_vals)) {
                     $va_vals = array();
                 }
                 return array_values(array_unique($va_vals));
             } elseif ($vs_link = $t_instance->getSelfRelationTableName()) {
                 // self relation
                 $vs_relationship_type_sql = '';
                 if ($va_relationship_types = caGetOption('restrictToRelationshipTypes', $pa_options, null)) {
                     $t_rel_type = new ca_relationship_types();
                     $va_relationship_type_ids = $t_rel_type->relationshipTypeListToIDs($vs_link, $va_relationship_types);
                     if (is_array($va_relationship_type_ids) && sizeof($va_relationship_type_ids)) {
                         $va_params[] = $va_relationship_type_ids;
                         $vs_relationship_type_sql = " AND ({$vs_link}.type_id IN (?))";
                     }
                 }
                 if ($va_relationship_types = caGetOption('excludeRelationshipTypes', $pa_options, null)) {
                     $t_rel_type = new ca_relationship_types();
                     $va_relationship_type_ids = $t_rel_type->relationshipTypeListToIDs($vs_link, $va_relationship_types);
                     if (is_array($va_relationship_type_ids) && sizeof($va_relationship_type_ids)) {
                         $va_params[] = $va_relationship_type_ids;
                         $vs_relationship_type_sql .= " AND ({$vs_link}.type_id NOT IN (?))";
                     }
                 }
                 $t_rel = $o_dm->getInstanceByTableName($vs_link, true);
                 $vs_left_field = $t_rel->getLeftTableFieldName();
                 $vs_right_field = $t_rel->getRightTableFieldName();
                 $qr_res = $o_db->query($x = "\n\t\t\t\t\t\tSELECT {$vs_link}.{$vs_left_field} \n\t\t\t\t\t\tFROM {$vs_link} \n\t\t\t\t\t\tWHERE {$vs_link}.{$vs_right_field} IN (?) {$vs_relationship_type_sql}\n\t\t\t\t\t", $va_params);
                 $va_vals = $qr_res->getAllFieldValues($vs_left_field);
                 $qr_res = $o_db->query("\n\t\t\t\t\t\tSELECT {$vs_link}.{$vs_right_field} \n\t\t\t\t\t\tFROM {$vs_link} \n\t\t\t\t\t\tWHERE {$vs_link}.{$vs_left_field} IN (?) {$vs_relationship_type_sql}\n\t\t\t\t\t", $va_params);
                 $va_vals = array_merge($va_vals, $qr_res->getAllFieldValues($vs_right_field));
                 if (!is_array($va_vals)) {
                     $va_vals = array();
                 }
                 return array_values(array_unique($va_vals));
             }
             break;
         default:
             throw new Exception("Unsupported mode in _getRelativeIDsForRowIDs: {$ps_mode}");
             break;
     }
     return array();
 }