/** * * * @param $ps_field - * @param $pa_options - * returnAsArray - * delimiter - * template - * locale - * returnAllLocales - Returns requested value in all locales for which it is defined. Default is false. Note that this is not supported for hierarchy specifications (eg. ca_objects.hierarchy). * direction - For hierarchy specifications (eg. ca_objects.hierarchy) this determines the order in which the hierarchy is returned. ASC will return the hierarchy root first while DESC will return it with the lowest node first. Default is ASC. * top - For hierarchy specifications (eg. ca_objects.hierarchy) this option, if set, will limit the returned hierarchy to the first X nodes from the root down. Default is to not limit. * bottom - For hierarchy specifications (eg. ca_objects.hierarchy) this option, if set, will limit the returned hierarchy to the first X nodes from the lowest node up. Default is to not limit. * hierarchicalDelimiter - Text to place between items in a hierarchy for a hierarchical specification (eg. ca_objects.hierarchy) when returning as a string * removeFirstItems - If set to a non-zero value, the specified number of items at the top of the hierarchy will be omitted. For example, if set to 2, the root and first child of the hierarchy will be omitted. Default is zero (don't delete anything). * checkAccess = array of access values to filter results by; if defined only items with the specified access code(s) are returned. Only supported for <table_name>.hierarchy.preferred_labels and <table_name>.children.preferred_labels because these returns sets of items. For <table_name>.parent.preferred_labels, which returns a single row at most, you should do access checking yourself. (Everything here applies equally to nonpreferred_labels) * sort = optional bundles to sort returned values on. Only supported for <table_name>.children.preferred_labels. The bundle specifiers are fields with or without tablename. * sort_direction = direction to sort results by, either 'asc' for ascending order or 'desc' for descending order; default is 'asc' * convertCodesToDisplayText = if true then non-preferred label type_ids are automatically converted to display text in the current locale; default is false (return non-preferred label type_id raw) */ public function get($ps_field, $pa_options = null) { $vs_template = isset($pa_options['template']) ? $pa_options['template'] : null; $vb_return_as_array = isset($pa_options['returnAsArray']) ? (bool) $pa_options['returnAsArray'] : false; $vb_return_all_locales = isset($pa_options['returnAllLocales']) ? (bool) $pa_options['returnAllLocales'] : false; $vs_delimiter = isset($pa_options['delimiter']) ? $pa_options['delimiter'] : ' '; $vb_convert_codes_to_display_text = isset($pa_options['convertCodesToDisplayText']) ? (bool) $pa_options['convertCodesToDisplayText'] : false; if ($vb_return_all_locales && !$vb_return_as_array) { $vb_return_as_array = true; } // if desired try to return values in a preferred language/locale $va_preferred_locales = null; if (isset($pa_options['locale']) && $pa_options['locale']) { $va_preferred_locales = array($pa_options['locale']); } // does get refer to an attribute? $va_tmp = explode('.', $ps_field); if ($va_tmp[1] == 'hierarchy' && sizeof($va_tmp) == 2) { $va_tmp[2] = 'preferred_labels'; $ps_field = join('.', $va_tmp); } $t_label = $this->getLabelTableInstance(); $t_instance = $this; if (sizeof($va_tmp) >= 3 && ($va_tmp[2] == 'preferred_labels' && (!$va_tmp[3] || $t_label->hasField($va_tmp[3]))) || $va_tmp[1] == 'hierarchy') { switch ($va_tmp[1]) { case 'parent': if ($this->isHierarchical() && ($vn_parent_id = $this->get($this->getProperty('HIERARCHY_PARENT_ID_FLD')))) { $t_instance = $this->getAppDatamodel()->getInstanceByTableNum($this->tableNum()); if (!$t_instance->load($vn_parent_id)) { $t_instance = $this; } else { unset($va_tmp[1]); $va_tmp = array_values($va_tmp); } } break; case 'children': if ($this->isHierarchical()) { unset($va_tmp[1]); // remove 'children' from field path $va_tmp = array_values($va_tmp); $vs_childless_path = join('.', $va_tmp); $va_data = array(); $va_children_ids = $this->getHierarchyChildren(null, array('idsOnly' => true)); if (is_array($va_children_ids) && sizeof($va_children_ids)) { $t_instance = $this->getAppDatamodel()->getInstanceByTableNum($this->tableNum()); $vb_check_access = is_array($pa_options['checkAccess']) && $t_instance->hasField('access'); $va_sort = isset($pa_options['sort']) ? $pa_options['sort'] : null; if (!is_array($va_sort) && $va_sort) { $va_sort = array($va_sort); } if (!is_array($va_sort)) { $va_sort = array(); } $vs_sort_direction = isset($pa_options['sort_direction']) && in_array(strtolower($pa_options['sort_direction']), array('asc', 'desc')) ? strtolower($pa_options['sort_direction']) : 'asc'; $qr_children = $this->makeSearchResult($this->tableName(), $va_children_ids); $vs_table = $this->tableName(); while ($qr_children->nextHit()) { if ($vb_check_access && !in_array($qr_children->get("{$vs_table}.access"), $pa_options['checkAccess'])) { continue; } $vs_sort_key = ''; foreach ($va_sort as $vs_sort) { $vs_sort_key .= $vs_sort ? $qr_children->get($vs_sort) : 0; } if (!is_array($va_data[$vs_sort_key])) { $va_data[$vs_sort_key] = array(); } $va_data[$vs_sort_key] = array_merge($va_data[$vs_sort_key], $qr_children->get($vs_childless_path, array_merge($pa_options, array('returnAsArray' => true)))); } ksort($va_data); if ($vs_sort_direction && $vs_sort_direction == 'desc') { $va_data = array_reverse($va_data); } $va_sorted_data = array(); foreach ($va_data as $vs_sort_key => $va_items) { foreach ($va_items as $vs_k => $vs_v) { $va_sorted_data[] = $vs_v; } } $va_data = $va_sorted_data; } if ($vb_return_as_array) { return $va_data; } else { return join($vs_delimiter, $va_data); } } break; case 'hierarchy': $vs_direction = isset($pa_options['direction']) ? strtoupper($pa_options['direction']) : null; if (!in_array($vs_direction, array('ASC', 'DESC'))) { $vs_direction = 'ASC'; } $vn_top = (int) isset($pa_options['top']) ? strtoupper($pa_options['top']) : 0; if ($vn_top < 0) { $vn_top = 0; } $vn_bottom = (int) isset($pa_options['bottom']) ? strtoupper($pa_options['bottom']) : 0; if ($vn_bottom < 0) { $vn_bottom = 0; } $vs_pk = $this->primaryKey(); $vs_label_table_name = $this->getLabelTableName(); $t_label_instance = $this->getLabelTableInstance(); if (!$vs_template && ($vs_display_field = $t_label_instance->hasField($va_tmp[2]) ? $t_label_instance->tableName() . "." . $va_tmp[2] : ($this->hasField($va_tmp[2]) ? $this->tableName() . "." . $va_tmp[2] : null))) { $vs_template = "^{$vs_display_field}"; } $vn_top_id = null; if (!($va_ancestor_list = $this->getHierarchyAncestors(null, array('idsOnly' => true, 'includeSelf' => true)))) { $va_ancestor_list = array(); } // TODO: this should really be in a model subclass if ($this->tableName() == 'ca_objects' && $this->getAppConfig()->get('ca_objects_x_collections_hierarchy_enabled') && ($vs_coll_rel_type = $this->getAppConfig()->get('ca_objects_x_collections_hierarchy_relationship_type'))) { require_once __CA_MODELS_DIR__ . '/ca_objects.php'; if ($this->getPrimaryKey() == $vn_top_id) { $t_object = $this; } else { $t_object = new ca_objects($vn_top_id); } if (is_array($va_collections = $t_object->getRelatedItems('ca_collections', array('restrictToRelationshipTypes' => $vs_coll_rel_type)))) { require_once __CA_MODELS_DIR__ . '/ca_collections.php'; $t_collection = new ca_collections(); foreach ($va_collections as $vn_i => $va_collection) { if ($va_collections_ancestor_list = $t_collection->getHierarchyAncestors($va_collection['collection_id'], array('idsOnly' => true, 'includeSelf' => true))) { $va_ancestor_list = array_merge($va_ancestor_list, $va_collections_ancestor_list); } break; // for now only process first collection (no polyhierarchies) } } } // remove root and children if so desired if (isset($pa_options['removeFirstItems']) && (int) $pa_options['removeFirstItems'] > 0) { for ($vn_i = 0; $vn_i < (int) $pa_options['removeFirstItems']; $vn_i++) { array_pop($va_ancestor_list); } } if ($vs_display_field != $va_tmp[2]) { if ($this->hasField($va_tmp[2])) { $vs_display_field = $va_tmp[2]; } } $vb_check_access = is_array($pa_options['checkAccess']) && $this->hasField('access'); if ($vb_check_access) { $va_access_values = $this->getFieldValuesForIDs($va_ancestor_list, array('access')); $va_ancestor_list = array(); foreach ($va_access_values as $vn_ancestor_id => $vn_access_value) { if (in_array($vn_access_value, $pa_options['checkAccess'])) { $va_ancestor_list[] = $vn_ancestor_id; } } } if ($vs_template) { $va_tmp = caProcessTemplateForIDs($vs_template, $this->tableName(), $va_ancestor_list, array('returnAsArray' => true)); } else { $va_tmp = $this->getPreferredDisplayLabelsForIDs($va_ancestor_list, array('returnAsArray' => true, 'returnAllLocales' => $vb_return_all_locales)); } if ($vn_top > 0) { $va_tmp = array_slice($va_tmp, sizeof($va_tmp) - $vn_top, $vn_top, true); } else { if ($vn_bottom > 0) { $va_tmp = array_slice($va_tmp, 0, $vn_bottom, true); } } if ($vs_direction == 'ASC') { $va_tmp = array_reverse($va_tmp, true); } if (caGetOption('returnAsLink', $pa_options, false)) { $va_tmp = caCreateLinksFromText(array_values($va_tmp), $this->tableName(), array_keys($va_tmp)); } if ($vb_return_as_array) { return $va_tmp; } else { $vs_hier_delimiter = isset($pa_options['hierarchicalDelimiter']) ? $pa_options['hierarchicalDelimiter'] : $pa_options['delimiter']; return join($vs_hier_delimiter, $va_tmp); } break; } } switch (sizeof($va_tmp)) { case 1: switch ($va_tmp[0]) { # --------------------------------------------- case 'preferred_labels': if (!$vb_return_as_array) { $va_labels = caExtractValuesByUserLocale($t_instance->getPreferredLabels(), null, $va_preferred_locales); $vs_disp_field = $this->getLabelDisplayField(); $va_values = array(); foreach ($va_labels as $vn_row_id => $va_label_list) { foreach ($va_label_list as $vn_i => $va_label) { if ($vs_template) { $va_values[] = caProcessTemplate($vs_template, $va_label, array('removePrefix' => 'preferred_labels.')); } else { $va_values[] = $va_label[$vs_disp_field]; } } } return join($vs_delimiter, $va_values); } else { $va_labels = $t_instance->getPreferredLabels(null, false); if ($vb_return_all_locales) { return $va_labels; } else { // Simplify array by getting rid of third level array which is unnecessary since // there is only ever one preferred label for a locale $va_labels = caExtractValuesByUserLocale($va_labels, null, $va_preferred_locales); $va_processed_labels = array(); foreach ($va_labels as $vn_label_id => $va_label_list) { $va_processed_labels[$vn_label_id] = $va_label_list[0]; } return $va_processed_labels; } } break; # --------------------------------------------- # --------------------------------------------- case 'nonpreferred_labels': if (!$vb_return_as_array) { $vs_disp_field = $this->getLabelDisplayField(); $va_labels = caExtractValuesByUserLocale($t_instance->getNonPreferredLabels(), null, $va_preferred_locales); $t_list = new ca_lists(); if ($vb_convert_codes_to_display_text) { $va_types = $t_list->getItemsForList($this->getLabelTableInstance()->getFieldInfo('type_id', 'LIST_CODE'), array('extractValuesByUserLocale' => true)); } $va_values = array(); foreach ($va_labels as $vn_row_id => $va_label_list) { foreach ($va_label_list as $vn_i => $va_label) { if ($vs_template) { $va_label_values = $va_label; $va_label_values['typename_singular'] = $va_types[$va_label['type_id']]['name_singular']; $va_label_values['typename_plural'] = $va_types[$va_label['type_id']]['name_plural']; if ($vb_convert_codes_to_display_text) { $va_label_values['type_id'] = $va_types[$va_label['type_id']]['name_singular']; } $va_values[] = caProcessTemplate($vs_template, $va_label_values, array('removePrefix' => 'nonpreferred_labels.')); } else { if ($vb_convert_codes_to_display_text && $vs_disp_field == 'type_id') { $va_values[] = $va_types[$va_label[$vs_disp_field]]['name_singular']; } else { $va_values[] = $va_label[$vs_disp_field]; } } } } return join($vs_delimiter, $va_values); $va_labels = caExtractValuesByUserLocale($t_instance->getNonPreferredLabels(null, false)); $vs_disp_field = $this->getLabelDisplayField(); $va_processed_labels = array(); foreach ($va_labels as $vn_label_id => $va_label_list) { foreach ($va_label_list as $vn_i => $va_label) { $va_processed_labels[] = $va_label[$vs_disp_field]; } } return join($vs_delimiter, $va_processed_labels); } else { $va_labels = $t_instance->getNonPreferredLabels(null, false); if ($vb_return_all_locales) { return $va_labels; } else { return caExtractValuesByUserLocale($va_labels, null, $va_preferred_locales); } } break; # --------------------------------------------- } break; case 2: case 3: if ($va_tmp[0] === $t_instance->tableName()) { switch ($va_tmp[1]) { # --------------------------------------------- case 'preferred_labels': if (!$vb_return_as_array) { if (isset($va_tmp[2]) && $va_tmp[2]) { $vs_disp_field = $va_tmp[2]; } else { $vs_disp_field = $this->getLabelDisplayField(); } $va_labels = caExtractValuesByUserLocale($t_instance->getPreferredLabels(), null, $va_preferred_locales); $va_values = array(); foreach ($va_labels as $vn_row_id => $va_label_list) { foreach ($va_label_list as $vn_i => $va_label) { if ($vs_template) { $va_values[] = caProcessTemplate($vs_template, $va_label, array('removePrefix' => 'preferred_labels.')); } else { $va_values[] = $va_label[$vs_disp_field]; } } } return join($vs_delimiter, $va_values); } else { $va_labels = $t_instance->getPreferredLabels(null, false); if (!$vb_return_all_locales) { // Simplify array by getting rid of third level array which is unnecessary since // there is only ever one preferred label for a locale $va_labels = caExtractValuesByUserLocale($va_labels, null, $va_preferred_locales); $va_processed_labels = array(); foreach ($va_labels as $vn_label_id => $va_label_list) { $va_processed_labels[$vn_label_id] = $va_label_list[0]; } $va_labels = $va_processed_labels; } if (isset($va_tmp[2]) && $va_tmp[2]) { // specific field if ($vb_return_all_locales) { foreach ($va_labels as $vn_label_id => $va_labels_by_locale) { foreach ($va_labels_by_locale as $vn_locale_id => $va_label_list) { foreach ($va_label_list as $vn_i => $va_label) { $va_labels[$vn_label_id][$vn_locale_id][$vn_i] = $va_label[$va_tmp[2]]; } } } } else { // get specified field value foreach ($va_labels as $vn_label_id => $va_label_info) { $va_labels[$vn_label_id] = $va_label_info[$va_tmp[2]]; } } } return $va_labels; } break; # --------------------------------------------- # --------------------------------------------- case 'nonpreferred_labels': if (!$vb_return_as_array) { if (isset($va_tmp[2]) && $va_tmp[2]) { $vs_disp_field = $va_tmp[2]; } else { $vs_disp_field = $this->getLabelDisplayField(); } $va_labels = caExtractValuesByUserLocale($t_instance->getNonPreferredLabels(), null, $va_preferred_locales); $t_list = new ca_lists(); if ($vb_convert_codes_to_display_text) { $va_types = $t_list->getItemsForList($this->getLabelTableInstance()->getFieldInfo('type_id', 'LIST_CODE'), array('extractValuesByUserLocale' => true)); } $va_values = array(); foreach ($va_labels as $vn_row_id => $va_label_list) { foreach ($va_label_list as $vn_i => $va_label) { if ($vs_template) { $va_label_values = $va_label; $va_label_values['typename_singular'] = $va_types[$va_label['type_id']]['name_singular']; $va_label_values['typename_plural'] = $va_types[$va_label['type_id']]['name_plural']; if ($vb_convert_codes_to_display_text) { $va_label_values['type_id'] = $va_types[$va_label['type_id']]['name_singular']; } $va_values[] = caProcessTemplate($vs_template, $va_label_values, array('removePrefix' => 'nonpreferred_labels.')); } else { if ($vb_convert_codes_to_display_text && $vs_disp_field == 'type_id') { $va_values[] = $va_types[$va_label[$vs_disp_field]]['name_singular']; } else { $va_values[] = $va_label[$vs_disp_field]; } } } } return join($vs_delimiter, $va_values); } else { $va_labels = $t_instance->getNonPreferredLabels(null, false); if (!$vb_return_all_locales) { $va_labels = caExtractValuesByUserLocale($va_labels, null, $va_preferred_locales); } if (isset($va_tmp[2]) && $va_tmp[2]) { // specific field if ($vb_return_all_locales) { foreach ($va_labels as $vn_label_id => $va_labels_by_locale) { foreach ($va_labels_by_locale as $vn_locale_id => $va_label_list) { foreach ($va_label_list as $vn_i => $va_label) { $va_labels[$vn_label_id][$vn_locale_id][$vn_i] = $va_label[$va_tmp[2]]; } } } } else { // get specified field value foreach ($va_labels as $vn_label_id => $va_label_info) { foreach ($va_label_info as $vn_id => $va_label) { $va_labels[$vn_label_id] = $va_label[$va_tmp[2]]; } } } } return $va_labels; } break; # --------------------------------------------- } } break; } return parent::get($ps_field, $pa_options); }
/** * Replace "^" prefixed tags (eg. ^forename) in a template with values from an array * * @param string $ps_template String with embedded tags. Tags are just alphanumeric strings prefixed with a caret ("^") * @param string $pm_tablename_or_num Table name or number of table from which values are being formatted * @param string $pa_row_ids An array of primary key values in the specified table to be pulled into the template * @param array $pa_options Supported options are: * returnAsArray = if true an array of processed template values is returned, otherwise the template values are returned as a string joined together with a delimiter. Default is false. * delimiter = value to string together template values with when returnAsArray is false. Default is ';' (semicolon) * relatedValues = array of field values to return in template when directly referenced. Array should be indexed numerically in parallel with $pa_row_ids * relationshipValues = array of field values to return in template for relationship when directly referenced. Should be indexed by row_id and then by relation_id * placeholderPrefix = attribute container to implicitly place primary record fields into. Ex. if the table is "ca_entities" and the placeholder is "address" then tags like ^city will resolve to ca_entities.address.city * requireLinkTags = if set then links are only added when explicitly defined with <l> tags. Default is to make the entire text a link in the absence of <l> tags. * resolveLinksUsing = * primaryIDs = row_ids for primary rows in related table, keyed by table name; when resolving ambiguous relationships the row_ids will be excluded from consideration. This option is rarely used and exists primarily to take care of a single * edge case: you are processing a template relative to a self-relationship such as ca_entities_x_entities that includes references to the subject table (ca_entities, in the case of ca_entities_x_entities). There are * two possible paths to take in this situations; primaryIDs lets you specify which ones you *don't* want to take by row_id. For interstitial editors, the ids will be set to a single id: that of the subject (Eg. ca_entities) row * from which the interstitial was launched. * sort = optional list of tag values to sort repeating values within a row template on. The tag must appear in the template. You can specify more than one tag by separating the tags with semicolons. * sortDirection = The direction of the sort of repeating values within a row template. May be either ASC (ascending) or DESC (descending). [Default is ASC] * linkTarget = Optional target to use when generating <l> tag-based links. By default links point to standard detail pages, but plugins may define linkTargets that point elsewhere. * skipIfExpression = skip the elements in $pa_row_ids for which the given expression does not evaluate true * includeBlankValuesInArray = include blank template values in returned array when returnAsArray is set. If you need the returned array of values to line up with the row_ids in $pa_row_ids this should be set. [Default is false] * * @return mixed Output of processed templates */ function caProcessTemplateForIDs($ps_template, $pm_tablename_or_num, $pa_row_ids, $pa_options = null) { foreach (array('request', 'template', 'restrictToTypes', 'restrict_to_types', 'restrict_to_relationship_types', 'restrictToRelationshipTypes', 'useLocaleCodes') as $vs_k) { unset($pa_options[$vs_k]); } if (!isset($pa_options['convertCodesToDisplayText'])) { $pa_options['convertCodesToDisplayText'] = true; } $pb_return_as_array = (bool) caGetOption('returnAsArray', $pa_options, false); if (($pa_sort = caGetOption('sort', $pa_options, null)) && !is_array($pa_sort)) { $pa_sort = explode(";", $pa_sort); } $ps_sort_direction = caGetOption('sortDirection', $pa_options, null, array('forceUppercase' => true)); if (!in_array($ps_sort_direction, array('ASC', 'DESC'))) { $ps_sort_direction = 'ASC'; } $pa_check_access = caGetOption('checkAccess', $pa_options, null); if (!is_array($pa_row_ids) || !sizeof($pa_row_ids) || !$ps_template) { return $pb_return_as_array ? array() : ""; } unset($pa_options['returnAsArray']); if (!isset($pa_options['requireLinkTags'])) { $pa_options['requireLinkTags'] = true; } $ps_skip_if_expression = caGetOption('skipIfExpression', $pa_options, false); $va_primary_ids = caGetOption("primaryIDs", $pa_options, null); $o_dm = Datamodel::load(); $ps_tablename = is_numeric($pm_tablename_or_num) ? $o_dm->getTableName($pm_tablename_or_num) : $pm_tablename_or_num; $ps_resolve_links_using = caGetOption('resolveLinksUsing', $pa_options, $ps_tablename); $t_instance = $o_dm->getInstanceByTableName($ps_tablename, true); if ($ps_resolve_links_using != $ps_tablename) { $t_resolve_links_instance = $o_dm->getInstanceByTableName($ps_resolve_links_using, true); $vs_resolve_links_using_pk = $t_resolve_links_instance->primaryKey(); } $vs_pk = $t_instance->primaryKey(); $vs_delimiter = isset($pa_options['delimiter']) ? $pa_options['delimiter'] : '; '; $ps_template = str_replace("^_parent", "^{$ps_resolve_links_using}.parent.preferred_labels", $ps_template); $ps_template = str_replace("^_hierarchy", "^{$ps_resolve_links_using}._hierarchyName", $ps_template); $va_related_values = isset($pa_options['relatedValues']) && is_array($pa_options['relatedValues']) ? $pa_options['relatedValues'] : array(); $va_relationship_values = isset($pa_options['relationshipValues']) && is_array($pa_options['relationshipValues']) ? $pa_options['relationshipValues'] : array(); $o_doc = str_get_dom($ps_template); // parse template $ps_template = str_replace("<~root~>", "", str_replace("</~root~>", "", $o_doc->html())); // replace template with parsed version; this allows us to do text find/replace later // Parse units from template $o_units = $o_doc('unit'); // only process non-nested <unit> tags $va_units = array(); $vn_unit_id = 1; foreach ($o_units as $o_unit) { if (!$o_unit) { continue; } $vs_html = str_replace("<~root~>", "", str_replace("</~root~>", "", $o_unit->html())); $vs_content = $o_unit->getInnerText(); // is this nested in another unit? We skip these foreach ($va_units as $va_tmp) { if (strpos($va_tmp['directive'], $vs_html) !== false) { continue 2; } } $va_units[] = $va_unit = array('tag' => $vs_unit_tag = "[[#{$vn_unit_id}]]", 'directive' => $vs_html, 'content' => $vs_content, 'relativeTo' => (string) $o_unit->getAttribute("relativeto"), 'delimiter' => ($vs_d = (string) $o_unit->getAttribute("delimiter")) ? $vs_d : null, 'restrictToTypes' => (string) $o_unit->getAttribute("restricttotypes"), 'restrictToRelationshipTypes' => (string) $o_unit->getAttribute("restricttorelationshiptypes"), 'sort' => explode(";", $o_unit->getAttribute("sort")), 'sortDirection' => (string) $o_unit->getAttribute("sortDirection"), 'skipIfExpression' => (string) $o_unit->getAttribute("skipIfExpression")); $ps_template = str_ireplace($va_unit['directive'], $vs_unit_tag, $ps_template); $vn_unit_id++; } $o_doc = str_get_dom($ps_template); // parse template again with units replaced by unit tags in the format [[#X]] $ps_template = str_replace("<~root~>", "", str_replace("</~root~>", "", $o_doc->html())); // replace template with parsed version; this allows us to do text find/replace later $va_tags = array(); if (preg_match_all(__CA_BUNDLE_DISPLAY_TEMPLATE_TAG_REGEX__, $ps_template, $va_matches)) { $va_tags = $va_matches[1]; } $va_directive_tags = array(); $va_directive_tag_vals = array(); $qr_res = caMakeSearchResult($ps_tablename, $pa_row_ids); if (!$qr_res) { return ''; } $va_proc_templates = array(); $vn_i = 0; $o_ifs = $o_doc("if"); // if $o_ifdefs = $o_doc("ifdef"); // if defined $o_ifnotdefs = $o_doc("ifnotdef"); // if not defined $o_mores = $o_doc("more"); // more tags - content suppressed if there are no defined values following the tag pair $o_betweens = $o_doc("between"); // between tags - content suppressed if there are not defined values on both sides of the tag pair $va_if = array(); foreach ($o_ifs as $o_if) { if (!$o_if) { continue; } $vs_html = $o_if->html(); $vs_content = $o_if->getInnerText(); $va_if[] = array('directive' => $vs_html, 'content' => $vs_content, 'rule' => $vs_rule = (string) $o_if->getAttribute('rule')); } foreach ($o_ifdefs as $o_ifdef) { if (!$o_ifdef) { continue; } $vs_code = (string) $o_ifdef->getAttribute('code'); $vs_code_proc = preg_replace("!%(.*)\$!", '', $vs_code); $va_directive_tags = array_merge($va_directive_tags, preg_split('![,\\|]{1}!', $vs_code_proc)); } foreach ($o_ifnotdefs as $o_ifnotdef) { if (!$o_ifnotdef) { continue; } $vs_code = (string) $o_ifnotdef->getAttribute('code'); $vs_code_proc = preg_replace("!%(.*)\$!", '', $vs_code); $va_directive_tags = array_merge($va_directive_tags, preg_split('![,\\|]{1}!', $vs_code_proc)); } $va_mores = array(); foreach ($o_mores as $o_more) { if (!$o_more) { continue; } $vs_html = str_replace("<~root~>", "", str_replace("</~root~>", "", $o_more->html())); $vs_content = $o_more->getInnerText(); $va_mores[] = array('directive' => $vs_html, 'content' => $vs_content); } $va_betweens = array(); foreach ($o_betweens as $o_between) { if (!$o_between) { continue; } $vs_html = str_replace("<~root~>", "", str_replace("</~root~>", "", $o_between->html())); $vs_content = $o_between->getInnerText(); $va_betweens[] = array('directive' => $vs_html, 'content' => $vs_content); } $va_resolve_links_using_row_ids = array(); $va_tag_val_list = $va_defined_tag_list = array(); $va_expression_vars = array(); /** @var $qr_res SearchResult */ while ($qr_res->nextHit()) { $vs_pk_val = $qr_res->get($vs_pk, array('checkAccess' => $pa_check_access)); if (is_array($pa_check_access) && sizeof($pa_check_access) && !in_array($qr_res->get("{$ps_tablename}.access"), $pa_check_access)) { continue; } $vs_template = $ps_template; // check if we skip this row because of skipIfExpression if (strlen($ps_skip_if_expression) > 0) { $va_expression_tags = caGetTemplateTags($ps_skip_if_expression); foreach ($va_expression_tags as $vs_expression_tag) { if (!isset($va_expression_vars[$vs_expression_tag])) { $va_expression_vars[$vs_expression_tag] = $qr_res->get($vs_expression_tag, array('assumeDisplayField' => true, 'returnIdno' => true, 'delimiter' => ';')); } } if (ExpressionParser::evaluate($ps_skip_if_expression, $va_expression_vars)) { continue; } } // Grab values for codes used in ifdef and ifnotdef directives $va_directive_tag_vals = array(); foreach ($va_directive_tags as $vs_directive_tag) { $va_directive_tag_vals[$vs_directive_tag] = $qr_res->get($vs_directive_tag, array('assumeDisplayField' => true, 'convertCodesToDisplayText' => true, 'dontUseElementTemplate' => true)); } $o_parsed_template = str_get_dom($vs_template); while (sizeof($vo_templates = $o_parsed_template('ifcount:not(:has(ifdef,ifndef,ifcount)),ifdef:not(:has(ifdef,ifndef,ifcount)),ifndef:not(:has(ifdef,ifndef,ifcount))')) > 0) { foreach ($vo_templates as $vn_index => $vo_element) { $vs_code = $vo_element->code; switch ($vo_element->tag) { case 'ifdef': if (strpos($vs_code, "|") !== false) { $vs_bool = 'OR'; $va_tag_list = explode("|", $vs_code); $vb_output = false; } else { $vs_bool = 'AND'; $va_tag_list = explode(",", $vs_code); $vb_output = true; } foreach ($va_tag_list as $vs_tag_to_test) { $vs_tag_to_test = preg_replace("!%.*\$!", "", $vs_tag_to_test); $vb_value_is_set = isset($va_directive_tag_vals[$vs_tag_to_test]) && strlen($va_directive_tag_vals[$vs_tag_to_test]) > 1; switch ($vs_bool) { case 'OR': if ($vb_value_is_set) { $vb_output = true; break 2; } // any must be defined; if any is defined output break; case 'AND': default: if (!$vb_value_is_set) { $vb_output = false; break 2; } // all must be defined; if any is not defined don't output break; } } if ($vb_output) { $vs_template = str_replace($vo_element->html(), $vo_element->getInnerText(), $vs_template); } else { $vs_template = str_replace($vo_element->html(), '', $vs_template); } break; case 'ifndef': if (strpos($vs_code, "|") !== false) { $vs_bool = 'OR'; $va_tag_list = explode("|", $vs_code); $vb_output = false; } else { $vs_bool = 'AND'; $va_tag_list = explode(",", $vs_code); $vb_output = true; } $vb_output = true; foreach ($va_tag_list as $vs_tag_to_test) { $vb_value_is_set = (bool) (isset($va_directive_tag_vals[$vs_tag_to_test]) && strlen($va_directive_tag_vals[$vs_tag_to_test]) > 0); switch ($vs_bool) { case 'OR': if (!$vb_value_is_set) { $vb_output = true; break 2; } // any must be not defined; if anything is not set output break; case 'AND': default: if ($vb_value_is_set) { $vb_output = false; break 2; } // all must be not defined; if anything is set don't output break; } } if ($vb_output) { $vs_template = str_replace($vo_element->html(), $vo_element->getInnerText(), $vs_template); } else { $vs_template = str_replace($vo_element->html(), '', $vs_template); } break; case 'ifcount': if (is_array($va_if_codes = preg_split("![\\|,;]+!", $vs_code))) { $vn_min = (int) $vo_element->min; $vn_max = (int) $vo_element->max; $va_restrict_to_types = preg_split("![,; ]+!", $vo_element->restrictToTypes); $va_restrict_to_relationship_types = preg_split("![,; ]+!", $vo_element->restrictToRelationshipTypes); $vn_count = 0; foreach ($va_if_codes as $vs_if_code) { if ($t_table = $o_dm->getInstanceByTableName($vs_if_code, true)) { $va_count_vals = $qr_res->get($vs_if_code . "." . $t_table->primaryKey(), array('restrictToTypes' => $va_restrict_to_types, 'restrictToRelationshipTypes' => $va_restrict_to_relationship_types, 'returnAsArray' => true, 'checkAccess' => $pa_check_access)); } else { $va_count_vals = $qr_res->get($vs_if_code, array('returnAsArray' => true, 'restrictToTypes' => $va_restrict_to_types, 'restrictToRelationshipTypes' => $va_restrict_to_relationship_types, 'checkAccess' => $pa_check_access)); } if (is_array($va_count_vals)) { $va_bits = explode(".", $vs_if_code); $vs_fld = array_pop($va_bits); foreach ($va_count_vals as $vs_count_val) { if (is_array($vs_count_val)) { if (isset($vs_count_val[$vs_fld]) && !trim($vs_count_val[$vs_fld])) { continue; } $vb_is_set = false; foreach ($vs_count_val as $vs_f => $vs_v) { if (trim($vs_v)) { $vb_is_set = true; break; } } if (!$vb_is_set) { continue; } } else { if (!trim($vs_count_val)) { continue; } } $vn_count++; } } } if ($vn_min <= $vn_count && ($vn_max >= $vn_count || !$vn_max)) { $vs_template = str_replace($vo_element->html(), $vo_element->getInnerText(), $vs_template); } else { $vs_template = str_replace($vo_element->html(), '', $vs_template); } } break; } } $o_parsed_template = str_get_dom($vs_template); // reparse } $va_proc_templates[$vn_i] = $vs_template; foreach ($va_units as $k => $va_unit) { if (!$va_unit['content']) { continue; } $va_relative_to_tmp = $va_unit['relativeTo'] ? explode(".", $va_unit['relativeTo']) : array($ps_tablename); if (!($t_rel_instance = $o_dm->getInstanceByTableName($va_relative_to_tmp[0], true))) { continue; } $vs_unit_delimiter = caGetOption('delimiter', $va_unit, $vs_delimiter); $vs_unit_skip_if_expression = caGetOption('skipIfExpression', $va_unit, false); // additional get options for pulling related records $va_get_options = array('returnAsArray' => true, 'checkAccess' => $pa_check_access); if ($va_unit['restrictToTypes'] && strlen($va_unit['restrictToTypes']) > 0) { $va_get_options['restrictToTypes'] = preg_split('![\\|,;]+!', $va_unit['restrictToTypes']); } if ($va_unit['restrictToRelationshipTypes'] && strlen($va_unit['restrictToRelationshipTypes']) > 0) { $va_get_options['restrictToRelationshipTypes'] = preg_split('![\\|,;]+!', $va_unit['restrictToRelationshipTypes']); } if ($va_unit['sort'] && is_array($va_unit['sort'])) { $va_get_options['sort'] = $va_unit['sort']; $va_get_options['sortDirection'] = $va_unit['sortDirection']; } if (sizeof($va_relative_to_tmp) == 1 && $va_relative_to_tmp[0] == $ps_tablename || sizeof($va_relative_to_tmp) >= 1 && $va_relative_to_tmp[0] == $ps_tablename && $va_relative_to_tmp[1] != 'related') { switch (strtolower($va_relative_to_tmp[1])) { case 'hierarchy': $va_relative_ids = $qr_res->get($t_rel_instance->tableName() . ".hierarchy." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'parent': $va_relative_ids = $qr_res->get($t_rel_instance->tableName() . ".parent." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'children': $va_relative_ids = $qr_res->get($t_rel_instance->tableName() . ".children." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; default: $va_relative_ids = array($vs_pk_val); break; } // process template for all records selected by unit tag $va_tmpl_val = caProcessTemplateForIDs($va_unit['content'], $va_relative_to_tmp[0], $va_relative_ids, array_merge($pa_options, array('sort' => $va_get_options['sort'], 'sortDirection' => $va_get_options['sortDirection'], 'returnAsArray' => true, 'delimiter' => $vs_unit_delimiter, 'resolveLinksUsing' => null, 'skipIfExpression' => $vs_unit_skip_if_expression))); $va_proc_templates[$vn_i] = str_ireplace($va_unit['tag'], join($vs_unit_delimiter, $va_tmpl_val), $va_proc_templates[$vn_i]); } else { switch (strtolower($va_relative_to_tmp[1])) { case 'hierarchy': $va_relative_ids = $qr_res->get($t_rel_instance->tableName() . ".hierarchy." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'parent': $va_relative_ids = $qr_res->get($t_rel_instance->tableName() . ".parent." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'children': $va_relative_ids = $qr_res->get($t_rel_instance->tableName() . ".children." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'related': $va_relative_ids = $qr_res->get($t_rel_instance->tableName() . ".related." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; default: if (method_exists($t_instance, 'isSelfRelationship') && $t_instance->isSelfRelationship()) { $va_relative_ids = array_values($t_instance->getRelatedIDsForSelfRelationship($va_primary_ids[$t_rel_instance->tableName()], array($vs_pk_val))); } else { $va_relative_ids = array_values($qr_res->get($t_rel_instance->tableName() . "." . $t_rel_instance->primaryKey(), $va_get_options)); } break; } $vs_tmpl_val = caProcessTemplateForIDs($va_unit['content'], $va_relative_to_tmp[0], $va_relative_ids, array_merge($pa_options, array('sort' => $va_unit['sort'], 'sortDirection' => $va_unit['sortDirection'], 'delimiter' => $vs_unit_delimiter, 'resolveLinksUsing' => null, 'skipIfExpression' => $vs_unit_skip_if_expression))); $va_proc_templates[$vn_i] = str_ireplace($va_unit['tag'], $vs_tmpl_val, $va_proc_templates[$vn_i]); } } if (!strlen(trim($va_proc_templates[$vn_i]))) { $va_proc_templates[$vn_i] = null; } if (!sizeof($va_tags)) { $vn_i++; continue; } // if there are no tags in the template then we don't need to process further if ($ps_resolve_links_using !== $ps_tablename) { $va_resolve_links_using_row_ids += $qr_res->get("{$ps_resolve_links_using}.{$vs_resolve_links_using_pk}", array('returnAsArray' => true, 'checkAccess' => $pa_check_access)); // we need to remove "primary_ids" from the list, since for self-relations these will be the side(s) of the relations we're viewing *from* if (is_array($va_primary_ids[$ps_resolve_links_using]) && sizeof($va_primary_ids[$ps_resolve_links_using])) { $va_resolve_links_using_row_ids = array_values(array_diff($va_resolve_links_using_row_ids, $va_primary_ids[$ps_resolve_links_using])); } } $va_tag_val_list[$vn_i] = array(); $va_defined_tag_list[$vn_i] = array(); $va_tag_opts = $va_tag_filters = array(); foreach ($va_tags as $vs_tag) { $va_tmp = explode('.', $vs_tag); $vs_last_element = $va_tmp[sizeof($va_tmp) - 1]; $va_tag_opt_tmp = explode("%", $vs_last_element); if (sizeof($va_tag_opt_tmp) > 1) { $vs_tag_bit = array_shift($va_tag_opt_tmp); // get rid of getspec foreach ($va_tag_opt_tmp as $vs_tag_opt_raw) { if (preg_match("!^\\[([^\\]]+)\\]\$!", $vs_tag_opt_raw, $va_matches)) { if (sizeof($va_filter = explode("=", $va_matches[1])) == 2) { $va_tag_filters[$va_filter[0]] = $va_filter[1]; } continue; } $va_tag_tmp = explode("=", $vs_tag_opt_raw); $va_tag_tmp[0] = trim($va_tag_tmp[0]); $va_tag_tmp[1] = trim($va_tag_tmp[1]); if (in_array($va_tag_tmp[0], array('delimiter', 'hierarchicalDelimiter'))) { $va_tag_tmp[1] = str_replace("_", " ", $va_tag_tmp[1]); } if (sizeof($va_tag_line_tmp = explode("|", $va_tag_tmp[1])) > 1) { $va_tag_opts[trim($va_tag_tmp[0])] = $va_tag_line_tmp; } else { $va_tag_opts[trim($va_tag_tmp[0])] = $va_tag_tmp[1]; } } $va_tmp[sizeof($va_tmp) - 1] = $vs_tag_bit; // remove option from tag-part array $vs_tag_proc = join(".", $va_tmp); $va_proc_templates[$vn_i] = str_replace($vs_tag, $vs_tag_proc, $va_proc_templates[$vn_i]); $vs_tag = $vs_tag_proc; } switch ($vs_tag) { case 'DATE': $vs_format = urldecode(caGetOption('format', $va_tag_opts, 'd M Y')); $va_proc_templates[$vn_i] = str_replace("^{$vs_tag}", date($vs_format), $va_proc_templates[$vn_i]); continue 2; break; } $pa_options = array_merge($pa_options, $va_tag_opts); // Default label tag to hierarchies if (isset($pa_options['showHierarchicalLabels']) && $pa_options['showHierarchicalLabels'] && $vs_tag == 'label') { unset($va_related_values[$vs_pk_val][$vs_tag]); unset($va_relationship_values[$vs_pk_val][$vs_tag]); $va_tmp = array($ps_tablename, 'hierarchy', 'preferred_labels'); } if (!isset($va_relationship_values[$vs_pk_val])) { $va_relationship_values[$vs_pk_val] = array(0 => null); } foreach ($va_relationship_values[$vs_pk_val] as $vn_relation_id => $va_relationship_value_array) { $vb_is_related = false; $va_val = null; if (isset($va_relationship_value_array[$vs_tag]) && !(isset($pa_options['showHierarchicalLabels']) && $pa_options['showHierarchicalLabels'] && $vs_tag == 'label')) { $va_val = array($vs_val = $va_relationship_value_array[$vs_tag]); } elseif (isset($va_relationship_value_array[$vs_tag])) { $va_val = array($vs_val = $va_relationship_value_array[$vs_tag]); } else { if (isset($va_related_values[$vs_pk_val][$vs_tag])) { $va_val = array($vs_val = $va_related_values[$vs_pk_val][$vs_tag]); } else { // // see if this is a reference to a related table // if (in_array($vs_tag, array("relationship_typename", "relationship_type_id", "relationship_typecode", "relationship_type_code"))) { $vb_is_related = true; switch ($vs_tag) { case 'relationship_typename': $vs_spec = 'preferred_labels.' . (caGetOption('orientation', $pa_options, 'LTOR') == 'LTOR' ? 'typename' : 'typename_reverse'); break; case 'relationship_type_id': $vs_spec = 'type_id'; break; case 'relationship_typecode': case 'relationship_type_code': default: $vs_spec = 'type_code'; break; } $vs_rel = $qr_res->get("ca_relationship_types.{$vs_spec}", array_merge($pa_options, $va_tag_opts, array('returnAsArray' => false))); $va_val = array($vs_rel); } elseif ($ps_tablename != $va_tmp[0] && ($t_tmp = $o_dm->getInstanceByTableName($va_tmp[0], true))) { // if the part of the tag before a "." (or the tag itself if there are no periods) is a related table then try to fetch it as related to the current record if (isset($pa_options['placeholderPrefix']) && $pa_options['placeholderPrefix'] && $va_tmp[0] != $pa_options['placeholderPrefix'] && sizeof($va_tmp) == 1) { $vs_get_spec = array_shift($va_tmp) . "." . $pa_options['placeholderPrefix']; if (sizeof($va_tmp) > 0) { $vs_get_spec .= "." . join(".", $va_tmp); } } else { $vs_get_spec = $vs_tag; } $va_spec_bits = explode(".", $vs_get_spec); if (sizeof($va_spec_bits) == 1 && $o_dm->getTableNum($va_spec_bits[0])) { $vs_get_spec .= ".preferred_labels"; } $va_additional_options = array('returnAsArray' => true, 'checkAccess' => $pa_check_access); $vs_hierarchy_name = null; $vb_is_hierarchy = false; if (in_array($va_spec_bits[1], array('hierarchy', '_hierarchyName'))) { $t_rel = $o_dm->getInstanceByTableName($va_spec_bits[0], true); switch ($t_rel->getProperty('HIERARCHY_TYPE')) { case __CA_HIER_TYPE_SIMPLE_MONO__: $va_additional_options['removeFirstItems'] = 1; break; case __CA_HIER_TYPE_MULTI_MONO__: $vs_hierarchy_name = $t_rel->getHierarchyName($qr_res->get($t_rel->tableName() . "." . $t_rel->primaryKey(), array('checkAccess' => $pa_check_access))); $va_additional_options['removeFirstItems'] = 1; break; } } if ($va_spec_bits[1] != '_hierarchyName') { $va_val = $qr_res->get($vs_get_spec, array_merge($pa_options, $va_additional_options, array('returnWithStructure' => true, 'returnBlankValues' => true, 'returnAllLocales' => true, 'useLocaleCodes' => false, 'filters' => $va_tag_filters, 'primaryIDs' => $va_primary_ids))); } else { $va_val = array(); } if (is_array($va_primary_ids) && isset($va_primary_ids[$va_spec_bits[0]]) && is_array($va_primary_ids[$va_spec_bits[0]])) { foreach ($va_primary_ids[$va_spec_bits[0]] as $vn_primary_id) { unset($va_val[$vn_primary_id]); } } if ($va_spec_bits[1] !== 'hierarchy') { $va_val = caExtractValuesByUserLocale($va_val); $va_val_tmp = array(); foreach ($va_val as $vn_d => $va_vals) { if (is_array($va_vals)) { $va_val_tmp = array_merge($va_val_tmp, array_values($va_vals)); } else { $va_val_tmp[] = $va_vals; } } $va_val = $va_val_tmp; } $va_val_proc = array(); switch ($va_spec_bits[1]) { case '_hierarchyName': if ($vs_hierarchy_name) { $va_val_proc[] = $vs_hierarchy_name; } break; case 'hierarchy': if (is_array($va_val) && sizeof($va_val) > 0) { $va_hier_list = array(); if ($vs_hierarchy_name) { array_unshift($va_hier_list, $vs_hierarchy_name); } $vs_name = end($va_spec_bits); foreach ($va_val as $va_hier) { $va_hier = caExtractValuesByUserLocale($va_hier); foreach ($va_hier as $va_hier_item) { foreach ($va_hier_item as $va_hier_value) { $va_hier_list[] = $va_hier_value[$vs_name] ? $va_hier_value[$vs_name] : array_shift($va_hier_value); } } } $va_val_proc[] = join(caGetOption("delimiter", $va_tag_opts, $vs_delimiter), $va_hier_list); } break; case 'parent': if (is_array($va_val)) { foreach ($va_val as $vm_label) { if (is_array($vm_label)) { $t_rel = $o_dm->getInstanceByTableName($va_spec_bits[0], true); if (!$t_rel || !method_exists($t_rel, "getLabelDisplayField")) { $va_val_proc[] = join("; ", $vm_label); } else { $va_val_proc[] = $vm_label[$t_rel->getLabelDisplayField()]; } } else { $va_val_proc[] = $vm_label; } } } break; default: $vs_terminal = end($va_spec_bits); foreach ($va_val as $va_val_container) { if (!is_array($va_val_container)) { if ($va_val_container) { $va_val_proc[] = $va_val_container; } continue; } // Add display field to *_labels terminals if (in_array($vs_terminal, array('preferred_labels', 'nonpreferred_labels')) && !$va_val_container[$vs_terminal]) { $t_rel = $o_dm->getInstanceByTableName($va_spec_bits[0], true); $vs_terminal = $t_rel->getLabelDisplayField(); } $va_val_proc[] = $va_val_container[$vs_terminal]; } break; } $va_val = $va_val_proc; $vb_is_related = true; } else { // // Handle non-related gets // // Default specifiers that end with a modifier to preferred labels if (sizeof($va_tmp) == 2 && in_array($va_tmp[1], array('hierarchy', 'children', 'parent', 'related'))) { array_push($va_tmp, 'preferred_labels'); } $vs_hierarchy_name = null; if (in_array($va_tmp[1], array('hierarchy', '_hierarchyName'))) { switch ($t_instance->getProperty('HIERARCHY_TYPE')) { case __CA_HIER_TYPE_SIMPLE_MONO__: $va_additional_options['removeFirstItems'] = 1; break; case __CA_HIER_TYPE_MULTI_MONO__: $vs_hierarchy_name = $t_instance->getHierarchyName($qr_res->get($t_instance->tableName() . "." . $t_instance->primaryKey(), array('checkAccess' => $pa_check_access))); $va_additional_options['removeFirstItems'] = 1; break; } } if ($va_tmp[0] == $ps_tablename) { array_shift($va_tmp); } // get rid of primary table if it's in the field spec if (!sizeof($va_tmp) && $t_instance->getProperty('LABEL_TABLE_NAME')) { $va_tmp[] = "preferred_labels"; } if (isset($pa_options['showHierarchicalLabels']) && $pa_options['showHierarchicalLabels']) { if (!in_array($va_tmp[0], array('hierarchy', 'children', 'parent', 'related')) && $va_tmp[1] == 'preferred_labels') { array_unshift($va_tmp, 'hierarchy'); } } if (isset($pa_options['placeholderPrefix']) && $pa_options['placeholderPrefix'] && $va_tmp[0] != $pa_options['placeholderPrefix']) { array_splice($va_tmp, -1, 0, $pa_options['placeholderPrefix']); } $vs_get_spec = "{$ps_tablename}." . join(".", $va_tmp); if (in_array($va_tmp[0], array('parent'))) { $va_val[] = $qr_res->get($vs_get_spec, array_merge($pa_options, $va_tag_opts, array('returnAsArray' => false))); } elseif ($va_tmp[0] == '_hierarchyName') { $va_val[] = $vs_hierarchy_name; } else { $va_val_tmp = $qr_res->get($vs_get_spec, array_merge($pa_options, $va_tag_opts, array('returnAsArray' => true, 'returnBlankValues' => true, 'assumeDisplayField' => true, 'filters' => $va_tag_filters, 'checkAccess' => $pa_check_access))); $va_val = array(); if (is_array($va_val_tmp)) { //$va_val_tmp = array_reverse($va_val_tmp); if ($va_tmp[0] == 'hierarchy') { if ($vs_hierarchy_name) { array_shift($va_val_tmp); // remove root array_unshift($va_val_tmp, $vs_hierarchy_name); // replace with hierarchy name } if ($vs_delimiter_tmp = caGetOption('hierarchicalDelimiter', $va_tag_opts)) { $vs_tag_val_delimiter = $vs_delimiter_tmp; } elseif ($vs_delimiter_tmp = caGetOption('hierarchicalDelimiter', $pa_options)) { $vs_tag_val_delimiter = $vs_delimiter_tmp; } elseif ($vs_delimiter_tmp = caGetOption('delimiter', $va_tag_opts, $vs_delimiter)) { $vs_tag_val_delimiter = $vs_delimiter_tmp; } else { $vs_tag_val_delimiter = $vs_delimiter; } } else { $vs_tag_val_delimiter = caGetOption('delimiter', $va_tag_opts, $vs_delimiter); } foreach ($va_val_tmp as $vn_attr_id => $vm_attr_val) { if (is_array($vm_attr_val)) { $va_val[] = join($vs_tag_val_delimiter, $vm_attr_val); } else { $va_val[] = $vm_attr_val; } } } if (sizeof($va_val) > 1 && $va_tmp[0] == 'hierarchy') { $vs_tag_val_delimiter = caGetOption('delimiter', $va_tag_opts, $vs_delimiter); $va_val = array(join($vs_tag_val_delimiter, $va_val)); } } } } } if (is_array($va_val)) { if (sizeof($va_val) > 0) { foreach ($va_val as $vn_j => $vs_val) { if (!is_array($va_tag_val_list[$vn_i][$vn_j][$vs_tag]) || !in_array($vs_val, $va_tag_val_list[$vn_i][$vn_j][$vs_tag])) { $va_tag_val_list[$vn_i][$vn_j][$vs_tag][] = $vs_val; if (is_array($vs_val) && sizeof($vs_val) || strlen($vs_val) > 0) { $va_defined_tag_list[$vn_i][$vn_j][$vs_tag] = true; } } } } else { $va_tag_val_list[$vn_i][0][$vs_tag] = null; $va_defined_tag_list[$vn_i][0][$vs_tag] = false; } } } } $vn_i++; } foreach ($va_tag_val_list as $vn_i => $va_tags_list) { // do sorting? if (is_array($pa_sort)) { $va_sorted_values = $va_sorted_values_tmp = array(); foreach ($va_tags_list as $vn_j => $va_values_by_field) { $vs_key = ''; foreach ($pa_sort as $vn_k => $vs_sort) { if (!isset($va_values_by_field[$vs_sort])) { continue; } $vs_subkey = null; foreach ($va_values_by_field[$vs_sort] as $vn_x => $vs_sort_subval) { if ($va_date = caDateToHistoricTimestamps($vs_sort_subval)) { // try to treat it as a date if ($ps_sort_direction == 'DESC' && ($va_date[0] < $vs_subkey || is_null($vs_subkey))) { $vs_subkey = $va_date[0]; } elseif ($va_date[0] > $vs_subkey || is_null($vs_subkey)) { $vs_subkey = $va_date[0]; } } else { $vs_sort_subval = str_pad($vs_sort_subval, 20, ' ', STR_PAD_LEFT); if ($ps_sort_direction == 'DESC' && ($vs_sort_subval < $vs_subkey || is_null($vs_subkey))) { $vs_subkey = $vs_sort_subval; } elseif ($vs_sort_subval > $vs_subkey || is_null($vs_subkey)) { $vs_subkey = $vs_sort_subval; } } } $vs_key .= $vs_subkey; $va_sorted_values_tmp[$vs_key][] = $va_values_by_field; } } ksort($va_sorted_values_tmp); foreach ($va_sorted_values_tmp as $vs_key => $va_value_list) { foreach ($va_value_list as $vn_x => $va_val) { $va_sorted_values[$vs_key . $vn_x] = $va_val; } } if ($ps_sort_direction == 'DESC') { $va_sorted_values = array_reverse($va_sorted_values); } if (sizeof($va_sorted_values) > 0) { $va_tag_val_list[$vn_i] = $va_tags_list = $va_sorted_values; } } $va_acc = array(); foreach ($va_tags_list as $vn_j => $va_tags) { $va_tag_list = array(); $va_pt_vals = array(); $vs_template = $va_proc_templates[$vn_i]; // Process <if> foreach ($va_if as $va_def_con) { if (ExpressionParser::evaluate($va_def_con['rule'], $va_tags)) { $vs_template = str_replace($va_def_con['directive'], $va_def_con['content'], $vs_template); } else { $vs_template = str_replace($va_def_con['directive'], '', $vs_template); } } // Process <more> tags foreach ($va_mores as $vn_more_index => $va_more) { if (($vn_pos = strpos($vs_template, $va_more['directive'])) !== false) { if (isset($va_mores[$vn_more_index + 1]) && ($vn_next_more_pos = strpos(substr($vs_template, $vn_pos + strlen($va_more['directive'])), $va_mores[$vn_more_index + 1]['directive'])) !== false) { $vn_next_more_pos += $vn_pos; $vs_partial_template = substr($vs_template, $vn_pos + strlen($va_more['directive']), $vn_next_more_pos - $vn_pos); } else { $vs_partial_template = substr($vs_template, $vn_pos + strlen($va_more['directive'])); } $vb_output = false; foreach (array_keys($va_defined_tag_list[$vn_i][$vn_j]) as $vs_defined_tag) { if (strpos($vs_partial_template, $vs_defined_tag) !== false) { // content is defined $vb_output = true; break; } } if ($vb_output) { $vs_template = preg_replace('!' . $va_more['directive'] . '!', $va_more['content'], $vs_template, 1); } else { $vs_template = preg_replace('!' . $va_more['directive'] . '!', '', $vs_template, 1); } } } // Process <between> tags - text to be output if it is between two defined values $va_between_positions = array(); foreach ($va_betweens as $vn_between_index => $va_between) { $vb_output_before = $vb_output_after = false; if (($vn_cur_pos = strpos($vs_template, $va_between['directive'])) !== false) { $va_between_positions[$vn_between_index] = $vn_cur_pos; // Get parts of template before tag and after tag $vs_partial_template_before = substr($vs_template, 0, $vn_cur_pos); $vs_partial_template_after = substr($vs_template, $vn_cur_pos + strlen($va_between['directive'])); // Only get the template between our current position and the next <between> tag if (isset($va_betweens[$vn_between_index + 1]) && ($vn_after_pos_relative = strpos($vs_partial_template_after, $va_betweens[$vn_between_index + 1]['directive'])) !== false) { $vs_partial_template_after = substr($vs_partial_template_after, 0, $vn_after_pos_relative); } // Check for defined value before and after tag foreach (array_keys($va_defined_tag_list[$vn_i][$vn_j]) as $vs_defined_tag) { if (strpos($vs_partial_template_before, $vs_defined_tag) !== false) { // content is defined $vb_output_after = true; } if (strpos($vs_partial_template_after, $vs_defined_tag) !== false) { // content is defined $vb_output_before = true; break; } if ($vb_output_before && $vb_output_after) { break; } } } if ($vb_output_before && $vb_output_after) { $vs_template = preg_replace('!' . $va_between['directive'] . '!', $va_between['content'], $vs_template, 1); } else { $vs_template = preg_replace('!' . $va_between['directive'] . '!', '', $vs_template, 1); } } // // Need to sort tags by length descending (longest first) // so that when we go to substitute and you have a tag followed by itself with a suffix // (ex. ^measurements and ^measurements2) we don't substitute both for the stub (ex. ^measurements) // $va_tags_tmp = array_keys($va_tags); usort($va_tags_tmp, function ($a, $b) { return strlen($b) - strlen($a); }); $vs_pt = $vs_template; foreach ($va_tags_tmp as $vs_tag) { $vs_pt = str_replace('^' . $vs_tag, is_array($va_tags[$vs_tag]) ? join(" | ", $va_tags[$vs_tag]) : $va_tags[$vs_tag], $vs_pt); } if ($vs_pt) { $va_pt_vals[] = $vs_pt; } if ($vs_acc_val = join(isset($pa_options['delimiter']) ? $pa_options['delimiter'] : $vs_delimiter, $va_pt_vals)) { $va_acc[] = $vs_acc_val; } } $va_proc_templates[$vn_i] = join($vs_delimiter, $va_acc); } if ($pb_return_as_array && !caGetOption('includeBlankValuesInArray', $pa_options, false)) { foreach ($va_proc_templates as $vn_i => $vs_template) { if (!strlen(trim($vs_template))) { unset($va_proc_templates[$vn_i]); } } } // Transform links $va_proc_templates = caCreateLinksFromText($va_proc_templates, $ps_resolve_links_using, $ps_resolve_links_using != $ps_tablename ? $va_resolve_links_using_row_ids : $pa_row_ids, null, caGetOption('linkTarget', $pa_options, null), array_merge(array('addRelParameter' => true), $pa_options)); // Kill any lingering tags (just in case) foreach ($va_proc_templates as $vn_i => $vs_proc_template) { $va_proc_templates[$vn_i] = preg_replace("!\\^([A-Za-z0-9_\\.]+[%]{1}[^ \\^\t\r\n\"\\'<>\\(\\)\\{\\}\\/\\[\\]]*|[A-Za-z0-9_\\.]+)!", "", $vs_proc_template); $va_proc_templates[$vn_i] = str_replace("<![CDATA[", "", $va_proc_templates[$vn_i]); $va_proc_templates[$vn_i] = str_replace("]]>", "", $va_proc_templates[$vn_i]); } if ($pb_return_as_array) { return $va_proc_templates; } return join($vs_delimiter, $va_proc_templates); }
/** * 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; }
/** * */ private static function _processChildren(SearchResult $pr_res, $po_nodes, array $pa_vals, array $pa_options = null) { if (!is_array($pa_options)) { $pa_options = []; } if (!$po_nodes) { return ''; } $vs_acc = ''; $ps_tablename = $pr_res->tableName(); $o_dm = Datamodel::load(); $t_instance = $o_dm->getInstanceByTableName($ps_tablename, true); $ps_delimiter = caGetOption('delimiter', $pa_options, '; '); $pb_is_case = caGetOption('isCase', $pa_options, false, ['castTo' => 'boolean']); $pb_quote = caGetOption('quote', $pa_options, false, ['castTo' => 'boolean']); $pa_primary_ids = caGetOption('primaryIDs', $pa_options, null); $pb_include_blanks = caGetOption('includeBlankValuesInArray', $pa_options, false); unset($pa_options['quote']); $vn_last_unit_omit_count = null; foreach ($po_nodes as $vn_index => $o_node) { switch ($vs_tag = strtolower($o_node->tag)) { case 'case': if (!$pb_is_case) { $vs_acc .= DisplayTemplateParser::_processChildren($pr_res, $o_node->children, $pa_vals, array_merge($pa_options, ['isCase' => true])); } break; case 'if': if (strlen($vs_rule = $o_node->rule) && ExpressionParser::evaluate($vs_rule, $pa_vals)) { $vs_acc .= DisplayTemplateParser::_processChildren($pr_res, $o_node->children, DisplayTemplateParser::_getValues($pr_res, DisplayTemplateParser::_getTags($o_node->children, $pa_options), $pa_options), $pa_options); if ($pb_is_case) { break 2; } } break; case 'ifdef': case 'ifnotdef': $vb_defined = DisplayTemplateParser::_evaluateCodeAttribute($pr_res, $o_node, ['index' => caGetOption('index', $pa_options, null), 'mode' => $vs_tag == 'ifdef' ? 'present' : 'not_present']); if ($vs_tag == 'ifdef' && $vb_defined || $vs_tag == 'ifnotdef' && $vb_defined) { // Make sure returned values are not empty $vs_acc .= DisplayTemplateParser::_processChildren($pr_res, $o_node->children, DisplayTemplateParser::_getValues($pr_res, DisplayTemplateParser::_getTags($o_node->children, $pa_options), $pa_options), $pa_options); if ($pb_is_case) { break 2; } } break; case 'ifcount': $vn_min = (int) $o_node->min; $vn_max = (int) $o_node->max; if (!is_array($va_codes = DisplayTemplateParser::_getCodesFromAttribute($o_node)) || !sizeof($va_codes)) { break; } $pa_check_access = $t_instance->hasField('access') ? caGetOption('checkAccess', $pa_options, null) : null; if (!is_array($pa_check_access) || !sizeof($pa_check_access)) { $pa_check_access = null; } $vb_bool = DisplayTemplateParser::_getCodesBooleanModeAttribute($o_node); $va_restrict_to_types = DisplayTemplateParser::_getCodesFromAttribute($o_node, ['attribute' => 'restrictToTypes']); $va_exclude_types = DisplayTemplateParser::_getCodesFromAttribute($o_node, ['attribute' => 'excludeTypes']); $va_restrict_to_relationship_types = DisplayTemplateParser::_getCodesFromAttribute($o_node, ['attribute' => 'restrictToRelationshipTypes']); $va_exclude_to_relationship_types = DisplayTemplateParser::_getCodesFromAttribute($o_node, ['attribute' => 'excludeRelationshipTypes']); $vm_count = $vb_bool == 'AND' ? 0 : []; foreach ($va_codes as $vs_code) { $va_vals = $pr_res->get($vs_code, ['checkAccess' => $pa_check_access, 'returnAsArray' => true, 'restrictToTypes' => $va_restrict_to_types, 'excludeTypes' => $va_exclude_types, 'restrictToRelationshipTypes' => $va_restrict_to_relationship_types, 'excludeRelationshipTypes' => $va_exclude_to_relationship_types]); if (is_array($va_vals)) { if ($vb_bool == 'AND') { $vm_count += sizeof($va_vals); } else { $vm_count[$vs_code] = sizeof($va_vals); } } } if ($vb_bool == 'AND') { if ($vn_min <= $vm_count && ($vn_max >= $vm_count || !$vn_max)) { $vs_acc .= DisplayTemplateParser::_processChildren($pr_res, $o_node->children, DisplayTemplateParser::_getValues($pr_res, DisplayTemplateParser::_getTags($o_node->children, $pa_options), $pa_options), $pa_options); if ($pb_is_case) { break 2; } } } else { $vb_all_have_count = true; foreach ($vm_count as $vs_code => $vn_count) { if (!($vn_min <= $vn_count && ($vn_max >= $vn_count || !$vn_max))) { $vb_all_have_count = false; break 2; } } if ($vb_all_have_count) { $vs_acc .= DisplayTemplateParser::_processChildren($pr_res, $o_node->children, $pa_vals, $pa_options); if ($pb_is_case) { break 2; } } } break; case 'more': // Does a placeholder with value follow this tag? // NOTE: We don't take into account <ifdef> and friends when finding a set placeholder; it may be set but not visible due to a conditional // This case is not covered at the moment on the assumption that if you're using <more> you're not using conditionals. This may or may not be a good assumption. for ($vn_i = $vn_index + 1; $vn_i < sizeof($po_nodes); $vn_i++) { if ($po_nodes[$vn_i] && $po_nodes[$vn_i]->tag == '~text~' && is_array($va_following_tags = caGetTemplateTags($po_nodes[$vn_i]->text))) { foreach ($va_following_tags as $vs_following_tag) { if (isset($pa_vals[$vs_following_tag]) && strlen($pa_vals[$vs_following_tag])) { $vs_acc .= DisplayTemplateParser::_processChildren($pr_res, $o_node->children, $pa_vals, $pa_options); if ($pb_is_case) { break 2; } } } } } break; case 'between': // Does a placeholder with value precede this tag? // NOTE: We don't take into account <ifdef> and friends when finding a set placeholder; it may be set but not visible due to a conditional // This case is not covered at the moment on the assumption that if you're using <between> you're not using conditionals. This may or may not be a good assumption. $vb_has_preceding_value = false; for ($vn_i = 0; $vn_i < $vn_index; $vn_i++) { if ($po_nodes[$vn_i] && $po_nodes[$vn_i]->tag == '~text~' && is_array($va_preceding_tags = caGetTemplateTags($po_nodes[$vn_i]->text))) { foreach ($va_preceding_tags as $vs_preceding_tag) { if (isset($pa_vals[$vs_preceding_tag]) && strlen($pa_vals[$vs_preceding_tag])) { $vb_has_preceding_value = true; } } } } if ($vb_has_preceding_value) { // Does it have a value immediately following it? for ($vn_i = $vn_index + 1; $vn_i < sizeof($po_nodes); $vn_i++) { if ($po_nodes[$vn_i] && $po_nodes[$vn_i]->tag == '~text~' && is_array($va_following_tags = caGetTemplateTags($po_nodes[$vn_i]->text))) { foreach ($va_following_tags as $vs_following_tag) { if (isset($pa_vals[$vs_following_tag]) && strlen($pa_vals[$vs_following_tag])) { $vs_acc .= DisplayTemplateParser::_processChildren($pr_res, $o_node->children, $pa_vals, $pa_options); if ($pb_is_case) { break 2; } } break; } } } } break; case 'expression': if ($vs_exp = trim($o_node->getInnerText())) { $vs_acc .= ExpressionParser::evaluate(DisplayTemplateParser::_processChildren($pr_res, $o_node->children, DisplayTemplateParser::_getValues($pr_res, DisplayTemplateParser::_getTags($o_node->children, $pa_options), $pa_options), array_merge($pa_options, ['quote' => true])), $pa_vals); if ($pb_is_case) { break 2; } } break; case 'unit': $va_relative_to_tmp = $o_node->relativeTo ? explode(".", $o_node->relativeTo) : [$ps_tablename]; if ($va_relative_to_tmp[0] && !($t_rel_instance = $o_dm->getInstanceByTableName($va_relative_to_tmp[0], true))) { continue; } $vn_last_unit_omit_count = 0; // <unit> attributes $vs_unit_delimiter = $o_node->delimiter ? (string) $o_node->delimiter : $ps_delimiter; $vb_unique = $o_node->unique ? (bool) $o_node->unique : false; $vb_aggregate_unique = $o_node->aggregateUnique ? (bool) $o_node->aggregateUnique : false; $vs_unit_skip_if_expression = (string) $o_node->skipIfExpression; $vn_start = (int) $o_node->start; $vn_length = (int) $o_node->length; $pa_check_access = $t_instance->hasField('access') ? caGetOption('checkAccess', $pa_options, null) : null; if (!is_array($pa_check_access) || !sizeof($pa_check_access)) { $pa_check_access = null; } // additional get options for pulling related records $va_get_options = ['returnAsArray' => true, 'checkAccess' => $pa_check_access]; $va_get_options['restrictToTypes'] = DisplayTemplateParser::_getCodesFromAttribute($o_node, ['attribute' => 'restrictToTypes']); $va_get_options['excludeTypes'] = DisplayTemplateParser::_getCodesFromAttribute($o_node, ['attribute' => 'excludeTypes']); $va_get_options['restrictToRelationshipTypes'] = DisplayTemplateParser::_getCodesFromAttribute($o_node, ['attribute' => 'restrictToRelationshipTypes']); $va_get_options['excludeRelationshipTypes'] = DisplayTemplateParser::_getCodesFromAttribute($o_node, ['attribute' => 'excludeRelationshipTypes']); if ($o_node->sort) { $va_get_options['sort'] = preg_split('![ ,;]+!', $o_node->sort); $va_get_options['sortDirection'] = $o_node->sortDirection; } if (sizeof($va_relative_to_tmp) == 1 && $va_relative_to_tmp[0] == $ps_tablename || sizeof($va_relative_to_tmp) >= 1 && $va_relative_to_tmp[0] == $ps_tablename && $va_relative_to_tmp[1] != 'related') { $vs_relative_to_container = null; switch (strtolower($va_relative_to_tmp[1])) { case 'hierarchy': $va_relative_ids = $pr_res->get($t_rel_instance->tableName() . ".hierarchy." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'parent': $va_relative_ids = $pr_res->get($t_rel_instance->tableName() . ".parent." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'children': $va_relative_ids = $pr_res->get($t_rel_instance->tableName() . ".children." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'siblings': $va_relative_ids = $pr_res->get($t_rel_instance->tableName() . ".siblings." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; default: // If relativeTo is not set to a valid attribute try to guess from template if ($t_rel_instance->isValidMetadataElement(join(".", array_slice($va_relative_to_tmp, 1, 1)), true)) { $vs_relative_to_container = join(".", array_slice($va_relative_to_tmp, 0, 2)); } else { $va_tags = caGetTemplateTags($o_node->getInnerText()); foreach ($va_tags as $vs_tag) { $va_tag = explode('.', $vs_tag); while (sizeof($va_tag) > 1) { $vs_end = array_pop($va_tag); if ($t_rel_instance->isValidMetadataElement($vs_end, true)) { $va_tag[] = $vs_end; $vs_relative_to_container = join(".", $va_tag); break 2; } } } } $va_relative_ids = array($pr_res->getPrimaryKey()); break; } // process template for all records selected by unit tag $va_tmpl_val = DisplayTemplateParser::evaluate($o_node->getInnerText(), $ps_tablename, $va_relative_ids, array_merge($pa_options, ['sort' => $va_get_options['sort'], 'sortDirection' => $va_get_options['sortDirection'], 'returnAsArray' => true, 'delimiter' => $vs_unit_delimiter, 'skipIfExpression' => $vs_unit_skip_if_expression, 'placeholderPrefix' => (string) $o_node->relativeTo, 'restrictToTypes' => $va_get_options['restrictToTypes'], 'excludeTypes' => $va_get_options['excludeTypes'], 'isUnit' => true, 'unitStart' => $vn_start, 'unitLength' => $vn_length, 'relativeToContainer' => $vs_relative_to_container, 'includeBlankValuesInTopLevelForPrefetch' => false, 'unique' => $vb_unique, 'aggregateUnique' => $vb_aggregate_unique])); if ($vb_unique) { $va_tmpl_val = array_unique($va_tmpl_val); } if ($vn_start > 0 || !is_null($vn_length)) { $vn_last_unit_omit_count = sizeof($va_tmpl_val) - ($vn_length - $vn_start); } if (caGetOption('returnAsArray', $pa_options, false)) { return $va_tmpl_val; } $vs_acc .= join($vs_unit_delimiter, $va_tmpl_val); if ($pb_is_case) { break 2; } } else { switch (strtolower($va_relative_to_tmp[1])) { case 'hierarchy': $va_relative_ids = $pr_res->get($t_rel_instance->tableName() . ".hierarchy." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'parent': $va_relative_ids = $pr_res->get($t_rel_instance->tableName() . ".parent." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'children': $va_relative_ids = $pr_res->get($t_rel_instance->tableName() . ".children." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'siblings': $va_relative_ids = $pr_res->get($t_rel_instance->tableName() . ".siblings." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'related': $va_relative_ids = $pr_res->get($t_rel_instance->tableName() . ".related." . $t_rel_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; default: if (method_exists($t_instance, 'isSelfRelationship') && $t_instance->isSelfRelationship() && is_array($pa_primary_ids) && isset($pa_primary_ids[$t_rel_instance->tableName()])) { $va_relative_ids = array_values($t_instance->getRelatedIDsForSelfRelationship($pa_primary_ids[$t_rel_instance->tableName()], array($pr_res->getPrimaryKey()))); } else { $va_relative_ids = $pr_res->get($t_rel_instance->primaryKey(true), $va_get_options); $va_relative_ids = is_array($va_relative_ids) ? array_values($va_relative_ids) : array(); } break; } $va_tmpl_val = DisplayTemplateParser::evaluate($o_node->getInnerText(), $va_relative_to_tmp[0], $va_relative_ids, array_merge($pa_options, ['sort' => $va_unit['sort'], 'sortDirection' => $va_unit['sortDirection'], 'delimiter' => $vs_unit_delimiter, 'returnAsArray' => true, 'skipIfExpression' => $vs_unit_skip_if_expression, 'placeholderPrefix' => (string) $o_node->relativeTo, 'restrictToTypes' => $va_get_options['restrictToTypes'], 'excludeTypes' => $va_get_options['excludeTypes'], 'isUnit' => true, 'unitStart' => $vn_start, 'unitLength' => $vn_length, 'includeBlankValuesInTopLevelForPrefetch' => false, 'unique' => $vb_unique, 'aggregateUnique' => $vb_aggregate_unique])); if ($vb_unique) { $va_tmpl_val = array_unique($va_tmpl_val); } if ($vn_start > 0 || !is_null($vn_length)) { $vn_num_vals = sizeof($va_tmpl_val); $va_tmpl_val = array_slice($va_tmpl_val, $vn_start, $vn_length > 0 ? $vn_length : null); $vn_last_unit_omit_count = $vn_num_vals - ($vn_length - $vn_start); } if (caGetOption('returnAsArray', $pa_options, false)) { return $va_tmpl_val; } $vs_acc .= join($vs_unit_delimiter, $va_tmpl_val); if ($pb_is_case) { break 2; } } break; case 'whenunitomits': if ($vn_last_unit_omit_count > 0) { $vs_proc_template = caProcessTemplate($o_node->getInnerText(), array_merge($pa_vals, ['omitcount' => (int) $vn_last_unit_omit_count]), ['quote' => $pb_quote]); $vs_acc .= $vs_proc_template; } break; default: if ($o_node->children && sizeof($o_node->children) > 0) { $vs_proc_template = DisplayTemplateParser::_processChildren($pr_res, $o_node->children, $pa_vals, $pa_options); } else { $vs_proc_template = caProcessTemplate($o_node->html(), $pa_vals, ['quote' => $pb_quote]); } if ($vs_tag === 'l') { $va_proc_templates = caCreateLinksFromText(["{$vs_proc_template}"], $ps_tablename, [$pr_res->getPrimaryKey()], null, caGetOption('linkTarget', $pa_options, null), array_merge(['addRelParameter' => true, 'requireLinkTags' => false], $pa_options)); $vs_proc_template = array_shift($va_proc_templates); } elseif (strlen($vs_tag) && $vs_tag[0] !== '~') { if ($o_node->children && sizeof($o_node->children) > 0) { $vs_attr = ''; if ($o_node->attributes) { foreach ($o_node->attributes as $attribute => $value) { $vs_attr .= " {$attribute}=\"" . htmlspecialchars(caProcessTemplate($value, $pa_vals, ['quote' => $pb_quote])) . "\""; } } $vs_proc_template = "<{$vs_tag}{$vs_attr}>{$vs_proc_template}</{$vs_tag}>"; } elseif ($o_node->attributes && sizeof($o_node->attributes) > 0) { $vs_attr = ''; foreach ($o_node->attributes as $attribute => $value) { $vs_attr .= " {$attribute}=\"" . htmlspecialchars(caProcessTemplate($value, $pa_vals, ['quote' => $pb_quote])) . "\""; } switch (strtolower($vs_tag)) { case 'br': case 'hr': case 'meta': case 'link': case 'base': case 'img': case 'embed': case 'param': case 'area': case 'col': case 'input': $vs_proc_template = "<{$vs_tag}{$vs_attr} />"; break; default: $vs_proc_template = "<{$vs_tag}{$vs_attr}></{$vs_tag}>"; break; } } else { $vs_proc_template = $o_node->html(); } } $vs_acc .= $vs_proc_template; break; } } return $vs_acc; }
/** * get() value for intrinsic * * @param array $pa_value_list * @param BaseModel $pt_instance * @param array Options * * @return array|string */ private function _getIntrinsicValue($pa_value_list, $pt_instance, $pa_options) { $vb_return_as_link = isset($pa_options['returnAsLink']) ? $pa_options['returnAsLink'] : false; $vb_get_direct_date = (bool) caGetOption(array('getDirectDate', 'GET_DIRECT_DATE'), $pa_options, false); $vb_sortable = isset($pa_options['sortable']) ? $pa_options['sortable'] : false; $va_path_components = $pa_options['pathComponents']; $va_field_info = $pa_options['fieldInfo']; $vs_pk = $pa_options['primaryKey']; $vs_table_name = $pt_instance->tableName(); // Handle specific intrinsic types switch ($va_field_info['FIELD_TYPE']) { case FT_DATERANGE: case FT_HISTORIC_DATERANGE: case FT_TIMESTAMP: case FT_DATETIME: case FT_HISTORIC_DATETIME: foreach ($pa_value_list as $vn_locale_id => $va_values) { if ($pa_options['useLocaleCodes']) { if (!$vn_locale_id || !($vm_locale_id = $this->opo_locales->localeIDToCode($vn_locale_id))) { $vm_locale_id = __CA_DEFAULT_LOCALE__; } } else { if (!($vm_locale_id = $vn_locale_id)) { $vm_locale_id = $this->opo_locales->localeCodeToID(__CA_DEFAULT_LOCALE__); } } foreach ($va_values as $vn_i => $va_value) { $va_ids[] = $vn_id = $va_value[$vs_pk]; if (in_array($va_field_info['FIELD_TYPE'], array(FT_TIMESTAMP, FT_DATETIME, FT_HISTORIC_DATETIME))) { $vs_prop = $va_value[$va_path_components['field_name']]; if (!$vb_get_direct_date && !$vb_sortable) { $this->opo_tep->init(); if ($va_field_info['FIELD_TYPE'] !== FT_HISTORIC_DATETIME) { $this->opo_tep->setUnixTimestamps($vs_prop, $vs_prop); } else { $this->opo_tep->setHistoricTimestamps($vs_prop, $vs_prop); } $vs_prop = $this->opo_tep->getText($pa_options); } } elseif ($vb_get_direct_date) { $vs_prop = $va_value[$va_field_info['START']]; } elseif ($vb_sortable) { $vs_prop = $va_value[$va_field_info['START']]; } else { $this->opo_tep->init(); if ($va_field_info['FIELD_TYPE'] == FT_DATERANGE) { $this->opo_tep->setUnixTimestamps($va_value[$va_field_info['START']], $va_value[$va_field_info['END']]); } else { $this->opo_tep->setHistoricTimestamps($va_value[$va_field_info['START']], $va_value[$va_field_info['END']]); } $vs_prop = $this->opo_tep->getText($pa_options); } if ($vb_return_as_link) { $vs_prop = array_shift(caCreateLinksFromText(array($vs_prop), $vs_table_name, array($vn_id))); } $va_return_values[$vn_id][$vm_locale_id] = $vs_prop; } } break; case FT_MEDIA: if (!($vs_version = $va_path_components['subfield_name'])) { $vs_version = "largeicon"; // TODO: fix } foreach ($pa_value_list as $vn_locale_id => $va_values) { if ($pa_options['useLocaleCodes']) { if (!$vn_locale_id || !($vm_locale_id = $this->opo_locales->localeIDToCode($vn_locale_id))) { $vm_locale_id = __CA_DEFAULT_LOCALE__; } } else { if (!($vm_locale_id = $vn_locale_id)) { $vm_locale_id = $this->opo_locales->localeCodeToID(__CA_DEFAULT_LOCALE__); } } foreach ($va_values as $vn_i => $va_value) { $va_ids[] = $vn_id = $va_value[$vs_pk]; $o_media_settings = new MediaProcessingSettings($va_path_components['table_name'], $va_path_components['field_name']); $va_versions = $o_media_settings->getMediaTypeVersions('*'); if (!isset($va_versions[$vs_version])) { $va_tmp = array_keys($va_versions); $vs_version = array_shift($va_tmp); } // See if an info element was passed, eg. ca_object_representations.media.icon.width should return the width of the media rather than a tag or url to the media $vs_info_element = $va_path_components['num_components'] == 4 ? $va_path_components['components'][3] : null; if ($pa_options['unserialize']) { $va_return_values[$vn_id][$vm_locale_id] = caUnserializeForDatabase($va_value[$va_path_components['field_name']]); } elseif ($vs_info_element) { $va_return_values[$vn_id][$vm_locale_id] = $this->getMediaInfo($va_path_components['table_name'] . '.' . $va_path_components['field_name'], $vs_version, $vs_info_element, $pa_options); } elseif (isset($pa_options['returnURL']) && $pa_options['returnURL']) { $va_return_values[$vn_id][$vm_locale_id] = $this->getMediaUrl($va_path_components['table_name'] . '.' . $va_path_components['field_name'], $vs_version, $pa_options); } elseif (isset($pa_options['returnPath']) && $pa_options['returnPath']) { $va_return_values[$vn_id][$vm_locale_id] = $this->getMediaPath($va_path_components['table_name'] . '.' . $va_path_components['field_name'], $vs_version, $pa_options); } else { $va_return_values[$vn_id][$vm_locale_id] = $this->getMediaTag($va_path_components['table_name'] . '.' . $va_path_components['field_name'], $vs_version, $pa_options); } } } break; default: // is intrinsic field in primary table foreach ($pa_value_list as $vn_locale_id => $va_values) { if ($pa_options['useLocaleCodes']) { if (!$vn_locale_id || !($vm_locale_id = $this->opo_locales->localeIDToCode($vn_locale_id))) { $vm_locale_id = __CA_DEFAULT_LOCALE__; } } else { if (!($vm_locale_id = $vn_locale_id)) { $vm_locale_id = $this->opo_locales->localeCodeToID(__CA_DEFAULT_LOCALE__); } } foreach ($va_values as $vn_i => $va_value) { $va_ids[] = $vn_id = $va_value[$vs_pk]; $vs_prop = $va_value[$va_path_components['field_name']]; if ($pa_options['unserialize']) { $vs_prop = caUnserializeForDatabase($vs_prop); } if ($pa_options['convertCodesToDisplayText']) { $vs_prop = $this->_convertCodeToDisplayText($vs_prop, $va_path_components, $pt_instance, $pa_options); } elseif ($pa_options['convertCodesToIdno']) { $vs_prop = $this->_convertCodeToIdno($vs_prop, $va_path_components, $pt_instance, $pa_options); } $va_return_values[$vn_id][$vm_locale_id] = $vs_prop; } } break; } if (!$pa_options['returnAllLocales']) { $va_return_values = caExtractValuesByUserLocale($va_return_values); } if ($pa_options['returnWithStructure']) { return is_array($va_return_values) ? $va_return_values : array(); } // // Flatten array for return as string or simple array value // $va_flattened_values = $this->_flattenArray($va_return_values, $pa_options); if ($pa_options['returnAsArray']) { return $va_flattened_values; } else { return sizeof($va_flattened_values) > 0 ? join($pa_options['delimiter'], $va_flattened_values) : null; } }
/** * Replace "^" tags (eg. ^forename) in a template with values from an array * * @param string $ps_template String with embedded tags. Tags are just alphanumeric strings prefixed with a caret ("^") * @param string $pm_tablename_or_num Table name or number of table from which values are being formatted * @param string $pa_row_ids An array of primary key values in the specified table to be pulled into the template * @param array $pa_options Supported options are: * returnAsArray = if true an array of processed template values is returned, otherwise the template values are returned as a string joined together with a delimiter. Default is false. * delimiter = value to string together template values with when returnAsArray is false. Default is ';' (semicolon) * relatedValues = array of field values to return in template when directly referenced. Array should be indexed numerically in parallel with $pa_row_ids * relationshipValues = array of field values to return in template for relationship when directly referenced. Should be indexed by row_id and then by relation_id * placeholderPrefix = attribute container to implicitly place primary record fields into. Ex. if the table is "ca_entities" and the placeholder is "address" then tags like ^city will resolve to ca_entities.address.city * requireLinkTags = if set then links are only added when explicitly defined with <l> tags. Default is to make the entire text a link in the absence of <l> tags. * resolveLinksUsing = * primaryIDs = row_ids for primary rows in related table, keyed by table name; when resolving ambiguous relationships the row_ids will be excluded from consideration. This option is rarely used and exists primarily to take care of a single * edge case: you are processing a template relative to a self-relationship such as ca_entities_x_entities that includes references to the subject table (ca_entities, in the case of ca_entities_x_entities). There are * two possible paths to take in this situations; primaryIDs lets you specify which ones you *don't* want to take by row_id. For interstitial editors, the ids will be set to a single id: that of the subject (Eg. ca_entities) row * from which the interstitial was launched. * @return mixed Output of processed templates */ function caProcessTemplateForIDs($ps_template, $pm_tablename_or_num, $pa_row_ids, $pa_options = null) { unset($pa_options['request']); unset($pa_options['template']); // we pass through options to get() and don't want templates if (!isset($pa_options['convertCodesToDisplayText'])) { $pa_options['convertCodesToDisplayText'] = true; } $pb_return_as_array = (bool) caGetOption('returnAsArray', $pa_options, false); if (!is_array($pa_row_ids) || !sizeof($pa_row_ids) || !$ps_template) { return $pb_return_as_array ? array() : ""; } unset($pa_options['returnAsArray']); if (!isset($pa_options['requireLinkTags'])) { $pa_options['requireLinkTags'] = true; } $va_primary_ids = caGetOption("primaryIDs", $pa_options, null); $o_dm = Datamodel::load(); $ps_tablename = is_numeric($pm_tablename_or_num) ? $o_dm->getTableName($pm_tablename_or_num) : $pm_tablename_or_num; $ps_resolve_links_using = caGetOption('resolveLinksUsing', $pa_options, $ps_tablename); $t_instance = $o_dm->getInstanceByTableName($ps_tablename, true); if ($ps_resolve_links_using != $ps_tablename) { $t_resolve_links_instance = $o_dm->getInstanceByTableName($ps_resolve_links_using, true); $vs_resolve_links_using_pk = $t_resolve_links_instance->primaryKey(); } $vs_pk = $t_instance->primaryKey(); $vs_delimiter = isset($pa_options['delimiter']) ? $pa_options['delimiter'] : '; '; $ps_template = str_replace("^_parent", "^{$ps_resolve_links_using}.parent.preferred_labels", $ps_template); $ps_template = str_replace("^_hierarchy", "^{$ps_resolve_links_using}._hierarchyName", $ps_template); $va_related_values = isset($pa_options['relatedValues']) && is_array($pa_options['relatedValues']) ? $pa_options['relatedValues'] : array(); $va_relationship_values = isset($pa_options['relationshipValues']) && is_array($pa_options['relationshipValues']) ? $pa_options['relationshipValues'] : array(); // Set up DomDocument XML parser $o_dom = new DOMDocument('1.0', 'utf-8'); $o_dom->preserveWhiteSpace = true; libxml_use_internal_errors(true); // don't reported mangled HTML errors $o_dom->loadHTML('<?xml encoding="utf-8">' . $ps_template); libxml_clear_errors(); // Parse units from template $o_xpath = new DOMXPath($o_dom); $o_units = $o_xpath->query('//unit[not(ancestor::unit)]'); // only find units not nested within other units (allows for units with units...) $va_units = array(); $ps_template = preg_replace("![\r\n\t]+!", "", html_entity_decode($ps_template)); //DomDocument kills newlines and tabs so we do the same to the template $ps_template = preg_replace("!relativeTo[ ]*\\=!i", "relativeto=", $ps_template); //DomDocument forces attribute names to all lower case so we need to adjust the template to match $ps_template = preg_replace("!restrictToTypes[ ]*\\=!i", "restricttotypes=", $ps_template); $ps_template = preg_replace("!restrictToRelationshipTypes[ ]*\\=!i", "restricttorelationshiptypes=", $ps_template); $ps_template = preg_replace("!([A-Za-z0-9]+)='([^']*)'!", "\$1=\"\$2\"", $ps_template); //DomDocument converts quotes around attributes from single to double quotes, so we need to normalize the template to match $ps_template = preg_replace("!\\>[ ]+\\<!", "><", $ps_template); $vn_unit_id = 1; foreach ($o_units as $o_unit) { if (!$o_unit) { continue; } $vs_html = (string) $o_dom->saveXML($o_unit); $vs_content = preg_replace("!^<[^\\>]+>!", "", $vs_html); $vs_content = preg_replace("!<[^\\>]+>\$!", "", $vs_content); $vs_content = preg_replace("!>[ ]+<\$!", "><", $vs_content); // DomDocument messes with white space and encodes entities so we normalize the directive here so the str_ireplace() replacement below doesn't fail $va_units[] = $va_unit = array('tag' => $vs_unit_tag = "[[#{$vn_unit_id}]]", 'directive' => preg_replace("![\r\n\t\"]+!", "", html_entity_decode($vs_html)), 'content' => $vs_content, 'relativeTo' => (string) $o_unit->getAttribute("relativeto"), 'delimiter' => (string) $o_unit->getAttribute("delimiter"), 'restrictToTypes' => (string) $o_unit->getAttribute("restricttotypes"), 'restrictToRelationshipTypes' => (string) $o_unit->getAttribute("restricttorelationshiptypes")); $ps_template = str_ireplace($va_unit['directive'], $vs_unit_tag, $ps_template); $vn_unit_id++; } $va_tags = array(); if (preg_match_all("!\\^([A-Za-z0-9_\\.]+[%]{1}[^ \\^\t\r\n\"\\'<>\\(\\)\\{\\}\\/\\[\\]]*|[A-Za-z0-9_\\.]+)!", $ps_template, $va_matches)) { $va_tags = $va_matches[1]; } $qr_res = $t_instance->makeSearchResult($ps_tablename, $pa_row_ids); if (!$qr_res) { return ''; } $va_proc_templates = array(); $vn_i = 0; // Parse template $o_dom->loadHTML('<?xml encoding="utf-8">' . $ps_template); libxml_clear_errors(); $o_if = $o_dom->getElementsByTagName("if"); // if $o_ifdefs = $o_dom->getElementsByTagName("ifdef"); // if defined $o_ifnotdefs = $o_dom->getElementsByTagName("ifnotdef"); // if not defined $o_mores = $o_dom->getElementsByTagName("more"); // more tags – content suppressed if there are no defined values following the tag pair $o_betweens = $o_dom->getElementsByTagName("between"); // between tags – content suppressed if there are not defined values on both sides of the tag pair $o_options = $o_dom->getElementsByTagName("options"); $va_if = array(); foreach ($o_if as $o_if) { if (!$o_if) { continue; } $vs_html = $o_dom->saveXML($o_if); $vs_content = preg_replace("!^<[^\\>]+>!", "", $vs_html); $vs_content = preg_replace("!<[^\\>]+>\$!", "", $vs_content); // // Hack to get around DomDocument trimming leading spaces off of parsed HTML // We try here to detect the trimming and shunt those spaces back where they belong. Seems to work :-) // if (preg_match("!([ ]+){$vs_content}!", $ps_template, $va_match_spaces)) { $vs_html = preg_replace("!{$vs_content}!", $va_match_spaces[1] . $vs_content, $vs_html); $vs_content = $va_match_spaces[1] . $vs_content; } $va_if[] = array('directive' => $vs_html, 'content' => $vs_content, 'rule' => $vs_rule = (string) $o_if->getAttribute('rule')); //$vs_code = preg_replace("!%(.*)$!", '', $vs_code); //if (!in_array($vs_code, $va_tags)) { $va_tags[] = $vs_code; } } //print_r($va_if); $va_ifdefs = array(); foreach ($o_ifdefs as $o_ifdef) { if (!$o_ifdef) { continue; } $vs_html = $o_dom->saveXML($o_ifdef); $vs_content = preg_replace("!^<[^\\>]+>!", "", $vs_html); $vs_content = preg_replace("!<[^\\>]+>\$!", "", $vs_content); // // Hack to get around DomDocument trimming leading spaces off of parsed HTML // We try here to detect the trimming and shunt those spaces back where they belong. Seems to work :-) // if (preg_match("!([ ]+){$vs_content}!", $ps_template, $va_match_spaces)) { $vs_html = preg_replace("!{$vs_content}!", $va_match_spaces[1] . $vs_content, $vs_html); $vs_content = $va_match_spaces[1] . $vs_content; } $va_ifdefs[$vs_code = (string) $o_ifdef->getAttribute('code')][] = array('directive' => $vs_html, 'content' => $vs_content); $vs_code = preg_replace("!%(.*)\$!", '', $vs_code); if (!in_array($vs_code, $va_tags)) { $va_tags[] = $vs_code; } } $va_ifnotdefs = array(); foreach ($o_ifnotdefs as $o_ifnotdef) { if (!$o_ifnotdef) { continue; } $vs_html = $o_dom->saveXML($o_ifnotdef); $vs_content = preg_replace("!^<[^\\>]+>!", "", $vs_html); $vs_content = preg_replace("!<[^\\>]+>\$!", "", $vs_content); // // Hack to get around DomDocument trimming leading spaces off of parsed HTML // We try here to detect the trimming and shunt those spaces back where they belong. Seems to work :-) // if (preg_match("!([ ]+){$vs_content}!", $ps_template, $va_match_spaces)) { $vs_html = preg_replace("!{$vs_content}!", $va_match_spaces[1] . $vs_content, $vs_html); $vs_content = $va_match_spaces[1] . $vs_content; } $va_ifnotdefs[$vs_code = (string) $o_ifnotdef->getAttribute('code')][] = array('directive' => $vs_html, 'content' => $vs_content); $vs_code = preg_replace("!%(.*)\$!", '', $vs_code); if (!in_array($vs_code, $va_tags)) { $va_tags[] = $vs_code; } } $va_mores = array(); foreach ($o_mores as $o_more) { if (!$o_more) { continue; } $vs_html = $o_dom->saveXML($o_more); $vs_content = preg_replace("!^<[^\\>]+>!", "", $vs_html); $vs_content = preg_replace("!<[^\\>]+>\$!", "", $vs_content); $va_mores[] = array('directive' => $vs_html, 'content' => $vs_content); } $va_betweens = array(); foreach ($o_betweens as $o_between) { if (!$o_between) { continue; } $vs_html = $o_dom->saveXML($o_between); $vs_content = preg_replace("!^<[^\\>]+>!", "", $vs_html); $vs_content = preg_replace("!<[^\\>]+>\$!", "", $vs_content); $va_betweens[] = array('directive' => $vs_html, 'content' => $vs_content); } $va_resolve_links_using_row_ids = array(); $va_tag_val_list = $va_defined_tag_list = array(); while ($qr_res->nextHit()) { $vs_pk_val = $qr_res->get($vs_pk); $va_proc_templates[$vn_i] = preg_replace("![\r\n\t]+!", "", html_entity_decode($ps_template)); // DomDocument messes with white space and encodes entities so we normalize things here so the str_ireplace() replacement below doesn't fail foreach ($va_units as $va_unit) { if (!$va_unit['content']) { continue; } $va_relative_to_tmp = $va_unit['relativeTo'] ? explode(".", $va_unit['relativeTo']) : array($ps_tablename); if (!($t_instance = $o_dm->getInstanceByTableName($va_relative_to_tmp[0], true))) { continue; } $vs_unit_delimiter = caGetOption('delimiter', $va_unit, '; '); // additional get options for pulling related records $va_get_options = array('returnAsArray' => true); if ($va_unit['restrictToTypes'] && strlen($va_unit['restrictToTypes']) > 0) { $va_get_options['restrictToTypes'] = explode('|', $va_unit['restrictToTypes']); } if ($va_unit['restrictToRelationshipTypes'] && strlen($va_unit['restrictToRelationshipTypes']) > 0) { $va_get_options['restrictToRelationshipTypes'] = explode('|', $va_unit['restrictToRelationshipTypes']); } if (sizeof($va_relative_to_tmp) == 1 && $va_relative_to_tmp[0] == $ps_tablename || sizeof($va_relative_to_tmp) >= 1 && $va_relative_to_tmp[0] == $ps_tablename && $va_relative_to_tmp[1] != 'related') { switch (strtolower($va_relative_to_tmp[1])) { case 'hierarchy': $va_relative_ids = $qr_res->get($t_instance->tableName() . ".hierarchy." . $t_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'parent': $va_relative_ids = $qr_res->get($t_instance->tableName() . ".parent." . $t_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'children': $va_relative_ids = $qr_res->get($t_instance->tableName() . ".children." . $t_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; default: $va_relative_ids = $pa_row_ids; break; } } else { switch (strtolower($va_relative_to_tmp[1])) { case 'hierarchy': $va_relative_ids = $qr_res->get($t_instance->tableName() . ".hierarchy." . $t_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'parent': $va_relative_ids = $qr_res->get($t_instance->tableName() . ".parent." . $t_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'children': $va_relative_ids = $qr_res->get($t_instance->tableName() . ".children." . $t_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; case 'related': $va_relative_ids = $qr_res->get($t_instance->tableName() . ".related." . $t_instance->primaryKey(), $va_get_options); $va_relative_ids = array_values($va_relative_ids); break; default: $va_relative_ids = $qr_res->get($t_instance->tableName() . "." . $t_instance->primaryKey(), $va_get_options); break; } } $vs_tmpl_val = caProcessTemplateForIDs($va_unit['content'], $va_relative_to_tmp[0], $va_relative_ids, array_merge($pa_options, array('restrictToTypes' => caGetOption('restrictToTypes', $va_get_options, null), 'restrictToRelationshipTypes' => caGetOption('restrictToRelationshipTypes', $va_get_options, null)), array('delimiter' => $vs_unit_delimiter, 'resolveLinksUsing' => null))); $va_proc_templates[$vn_i] = str_ireplace($va_unit['tag'], $vs_tmpl_val, $va_proc_templates[$vn_i]); } if (!strlen(trim($va_proc_templates[$vn_i]))) { $va_proc_templates[$vn_i] = null; } if (!sizeof($va_tags)) { continue; } // if there are no tags in the template then we don't need to process further if ($ps_resolve_links_using != $ps_tablename) { $va_resolve_links_using_row_ids[] = $qr_res->get("{$ps_resolve_links_using}.{$vs_resolve_links_using_pk}"); } $va_tag_val_list[$vn_i] = array(); $va_defined_tag_list[$vn_i] = array(); $va_tag_opts = array(); foreach ($va_tags as $vs_tag) { $va_tmp = explode('.', $vs_tag); $vs_last_element = $va_tmp[sizeof($va_tmp) - 1]; $va_tag_opt_tmp = explode("%", $vs_last_element); if (sizeof($va_tag_opt_tmp) > 1) { $vs_tag_bit = array_shift($va_tag_opt_tmp); // get rid of getspec foreach ($va_tag_opt_tmp as $vs_tag_opt_raw) { $va_tag_tmp = explode("=", $vs_tag_opt_raw); $va_tag_tmp[0] = trim($va_tag_tmp[0]); $va_tag_tmp[1] = trim($va_tag_tmp[1]); if (in_array($va_tag_tmp[0], array('delimiter', 'hierarchicalDelimiter'))) { $va_tag_tmp[1] = str_replace("_", " ", $va_tag_tmp[1]); } if (sizeof($va_tag_line_tmp = explode("|", $va_tag_tmp[1])) > 1) { $va_tag_opts[trim($va_tag_tmp[0])] = $va_tag_line_tmp; } else { $va_tag_opts[trim($va_tag_tmp[0])] = $va_tag_tmp[1]; } } $va_tmp[sizeof($va_tmp) - 1] = $vs_tag_bit; // remove option from tag-part array $vs_tag_proc = join(".", $va_tmp); $va_proc_templates[$vn_i] = str_replace($vs_tag, $vs_tag_proc, $va_proc_templates[$vn_i]); $vs_tag = $vs_tag_proc; } $pa_options = array_merge($pa_options, $va_tag_opts); // Default label tag to hierarchies if (isset($pa_options['showHierarchicalLabels']) && $pa_options['showHierarchicalLabels'] && $vs_tag == 'label') { unset($va_related_values[$vs_pk_val][$vs_tag]); unset($va_relationship_values[$vs_pk_val][$vs_tag]); $va_tmp = array($ps_tablename, 'hierarchy', 'preferred_labels'); } if (!isset($va_relationship_values[$vs_pk_val])) { $va_relationship_values[$vs_pk_val] = array(0 => null); } foreach ($va_relationship_values[$vs_pk_val] as $vn_relation_id => $va_relationship_value_array) { $vb_is_related = false; $va_val = null; if (isset($va_relationship_value_array[$vs_tag]) && !(isset($pa_options['showHierarchicalLabels']) && $pa_options['showHierarchicalLabels'] && $vs_tag == 'label')) { $va_val = array($vs_val = $va_relationship_value_array[$vs_tag]); } else { if (isset($va_related_values[$vs_pk_val][$vs_tag])) { $va_val = array($vs_val = $va_related_values[$vs_pk_val][$vs_tag]); } else { // // see if this is a reference to a related table // if ($ps_tablename != $va_tmp[0] && ($t_tmp = $o_dm->getInstanceByTableName($va_tmp[0], true))) { // if the part of the tag before a "." (or the tag itself if there are no periods) is a related table then try to fetch it as related to the current record if (isset($pa_options['placeholderPrefix']) && $pa_options['placeholderPrefix'] && $va_tmp[0] != $pa_options['placeholderPrefix'] && sizeof($va_tmp) == 1) { $vs_get_spec = array_shift($va_tmp) . "." . $pa_options['placeholderPrefix']; if (sizeof($va_tmp) > 0) { $vs_get_spec .= "." . join(".", $va_tmp); } } else { $vs_get_spec = $vs_tag; } $va_spec_bits = explode(".", $vs_get_spec); if (sizeof($va_spec_bits) == 1 && $o_dm->getTableNum($va_spec_bits[0])) { $vs_get_spec .= ".preferred_labels"; } $va_additional_options = array('returnAsArray' => true); $vs_hierarchy_name = null; if (in_array($va_spec_bits[1], array('hierarchy', '_hierarchyName'))) { $t_rel = $o_dm->getInstanceByTableName($va_spec_bits[0], true); switch ($t_rel->getProperty('HIERARCHY_TYPE')) { case __CA_HIER_TYPE_SIMPLE_MONO__: $va_additional_options['removeFirstItems'] = 1; break; case __CA_HIER_TYPE_MULTI_MONO__: $vs_hierarchy_name = $t_rel->getHierarchyName($qr_res->get($t_rel->tableName() . "." . $t_rel->primaryKey())); $va_additional_options['removeFirstItems'] = 1; break; } } if ($va_spec_bits[1] != '_hierarchyName') { $va_val = $qr_res->get($vs_get_spec, array_merge($pa_options, $va_additional_options, array("returnAsArray" => true, "returnAllLocales" => true))); } else { $va_val = array(); } if (is_array($va_primary_ids) && isset($va_primary_ids[$va_spec_bits[0]]) && is_array($va_primary_ids[$va_spec_bits[0]])) { foreach ($va_primary_ids[$va_spec_bits[0]] as $vn_primary_id) { unset($va_val[$vn_primary_id]); } } $va_val = caExtractValuesByUserLocale($va_val); $va_val_tmp = array(); foreach ($va_val as $vn_d => $va_vals) { $va_val_tmp = array_merge($va_val_tmp, $va_vals); } $va_val = $va_val_tmp; $va_val_proc = array(); switch ($va_spec_bits[1]) { case '_hierarchyName': if ($vs_hierarchy_name) { $va_val_proc[] = $vs_hierarchy_name; } break; case 'hierarchy': if (is_array($va_val) && sizeof($va_val) > 0) { if ($vs_hierarchy_name) { array_unshift($va_val, $vs_hierarchy_name); } foreach ($va_val as $va_hier) { if (!is_array($va_hier)) { $va_hier = array($va_hier); } $va_val_proc[] = join(caGetOption("delimiter", $va_tag_opts, "; "), $va_hier); } } break; case 'parent': if (is_array($va_val)) { foreach ($va_val as $va_label) { $va_val_proc[] = $va_label['name']; } } break; default: $vs_terminal = end($va_spec_bits); foreach ($va_val as $va_val_container) { if (!is_array($va_val_container)) { if ($va_val_container) { $va_val_proc[] = $va_val_container; } continue; } $va_val_proc[] = $va_val_container[$vs_terminal]; } break; } $va_val = $va_val_proc; $vb_is_related = true; } else { // // Handle non-related gets // // Default specifiers that end with a modifier to preferred labels if (sizeof($va_tmp) == 2 && in_array($va_tmp[1], array('hierarchy', 'children', 'parent', 'related'))) { array_push($va_tmp, 'preferred_labels'); } $vs_hierarchy_name = null; if (in_array($va_tmp[1], array('hierarchy', '_hierarchyName'))) { switch ($t_instance->getProperty('HIERARCHY_TYPE')) { case __CA_HIER_TYPE_SIMPLE_MONO__: $va_additional_options['removeFirstItems'] = 1; break; case __CA_HIER_TYPE_MULTI_MONO__: $vs_hierarchy_name = $t_instance->getHierarchyName($qr_res->get($t_instance->tableName() . "." . $t_instance->primaryKey())); $va_additional_options['removeFirstItems'] = 1; break; } } if ($va_tmp[0] == $ps_tablename) { array_shift($va_tmp); } // get rid of primary table if it's in the field spec if (!sizeof($va_tmp) && $t_instance->getProperty('LABEL_TABLE_NAME')) { $va_tmp[] = "preferred_labels"; } if (isset($pa_options['showHierarchicalLabels']) && $pa_options['showHierarchicalLabels']) { if (!in_array($va_tmp[0], array('hierarchy', 'children', 'parent', 'related')) && $va_tmp[1] == 'preferred_labels') { array_unshift($va_tmp, 'hierarchy'); } } if (isset($pa_options['placeholderPrefix']) && $pa_options['placeholderPrefix'] && $va_tmp[0] != $pa_options['placeholderPrefix']) { array_splice($va_tmp, -1, 0, $pa_options['placeholderPrefix']); } $vs_get_spec = "{$ps_tablename}." . join(".", $va_tmp); if (in_array($va_tmp[0], array('parent'))) { $va_val[] = $qr_res->get($vs_get_spec, array_merge($pa_options, $va_tag_opts, array('returnAsArray' => false))); } else { $va_val_tmp = $qr_res->get($vs_get_spec, array_merge($pa_options, $va_tag_opts, array('returnAsArray' => true))); $va_val = array(); if (is_array($va_val_tmp)) { foreach ($va_val_tmp as $vn_attr_id => $vm_attr_val) { if (is_array($vm_attr_val)) { if ($va_tmp[0] == 'hierarchy') { if ($vs_hierarchy_name) { array_shift($vm_attr_val); // remove root array_unshift($vm_attr_val, $vs_hierarchy_name); // replace with hierarchy name } if ($vs_delimiter_tmp = caGetOption('hierarchicalDelimiter', $va_tag_opts)) { $vs_tag_val_delimiter = $vs_delimiter_tmp; } elseif ($vs_delimiter_tmp = caGetOption('hierarchicalDelimiter', $pa_options)) { $vs_tag_val_delimiter = $vs_delimiter_tmp; } else { $vs_tag_val_delimiter = caGetOption('delimiter', $va_tag_opts, $vs_delimiter); } } else { $vs_tag_val_delimiter = caGetOption('delimiter', $va_tag_opts, $vs_delimiter); } $va_val[] = join($vs_tag_val_delimiter, $vm_attr_val); } else { $va_val[] = $vm_attr_val; } } } if (sizeof($va_val) > 1 && $va_tmp[0] == 'hierarchy') { $vs_tag_val_delimiter = caGetOption('delimiter', $va_tag_opts, $vs_delimiter); $va_val = array(join($vs_tag_val_delimiter, $va_val)); } } } } } if (is_array($va_val)) { if (sizeof($va_val) > 0) { foreach ($va_val as $vn_j => $vs_val) { if (!is_array($va_tag_val_list[$vn_i][$vn_j][$vs_tag]) || !in_array($vs_val, $va_tag_val_list[$vn_i][$vn_j][$vs_tag])) { $va_tag_val_list[$vn_i][$vn_j][$vs_tag][] = $vs_val; if (is_array($vs_val) && sizeof($vs_val) || strlen($vs_val) > 0) { $va_defined_tag_list[$vn_i][$vn_j][$vs_tag] = true; } } } } else { $va_tag_val_list[$vn_i][0][$vs_tag] = null; $va_defined_tag_list[$vn_i][0][$vs_tag] = false; } } } } $vn_i++; } foreach ($va_tag_val_list as $vn_i => $va_tags_list) { $va_acc = array(); foreach ($va_tags_list as $vn_j => $va_tags) { $va_tag_list = array(); $va_pt_vals = array(); $vs_template = $va_proc_templates[$vn_i]; // Process <if> foreach ($va_if as $va_def_con) { if (ExpressionParser::evaluate($va_def_con['rule'], $va_tags)) { $vs_template = str_replace($va_def_con['directive'], $va_def_con['content'], $vs_template); } else { $vs_template = str_replace($va_def_con['directive'], '', $vs_template); } } // Process <ifdef> (IF DEFined) foreach ($va_ifdefs as $vs_code => $va_def_con) { if (strpos($vs_code, "|") !== false) { $vs_bool = 'OR'; $va_tag_list = explode("|", $vs_code); $vb_output = false; } else { $vs_bool = 'AND'; $va_tag_list = explode(",", $vs_code); $vb_output = true; } foreach ($va_tag_list as $vs_tag_to_test) { $vb_value_is_set = (bool) (isset($va_tags[$vs_tag_to_test]) && sizeof($va_tags[$vs_tag_to_test]) > 1 || sizeof($va_tags[$vs_tag_to_test]) == 1 && strlen($va_tags[$vs_tag_to_test][0]) > 0); switch ($vs_bool) { case 'OR': if ($vb_value_is_set) { $vb_output = true; break 2; } // any must be defined; if any is defined output break; case 'AND': default: if (!$vb_value_is_set) { $vb_output = false; break 2; } // all must be defined; if any is not defined don't output break; } } foreach ($va_def_con as $va_ifdef) { if ($vb_output) { $vs_template = str_replace($va_ifdef['directive'], $va_ifdef['content'], $vs_template); } else { $vs_template = str_replace($va_ifdef['directive'], '', $vs_template); } } } // Process <ifnotdef> (IF NOT DEFined) foreach ($va_ifnotdefs as $vs_code => $va_notdef_con) { if (strpos($vs_code, "|") !== false) { $vs_bool = 'OR'; $va_tag_list = explode("|", $vs_code); $vb_output = false; } else { $vs_bool = 'AND'; $va_tag_list = explode(",", $vs_code); $vb_output = true; } $vb_output = true; foreach ($va_tag_list as $vs_tag_to_test) { $vb_value_is_set = (bool) (isset($va_tags[$vs_tag_to_test]) && sizeof($va_tags[$vs_tag_to_test]) > 1 || sizeof($va_tags[$vs_tag_to_test]) == 1 && strlen($va_tags[$vs_tag_to_test][0]) > 0); switch ($vs_bool) { case 'OR': if (!$vb_value_is_set) { $vb_output = true; break 2; } // any must be not defined; if anything is not set output break; case 'AND': default: if ($vb_value_is_set) { $vb_output = false; break 2; } // all must be not defined; if anything is set don't output break; } } foreach ($va_notdef_con as $va_ifnotdef) { if ($vb_output) { $vs_template = str_replace($va_ifnotdef['directive'], $va_ifnotdef['content'], $vs_template); } else { $vs_template = str_replace($va_ifnotdef['directive'], '', $vs_template); } } } // Process <more> tags foreach ($va_mores as $vn_more_index => $va_more) { if (($vn_pos = strpos($vs_template, $va_more['directive'])) !== false) { if (isset($va_mores[$vn_more_index + 1]) && ($vn_next_more_pos = strpos(substr($vs_template, $vn_pos + strlen($va_more['directive'])), $va_mores[$vn_more_index + 1]['directive'])) !== false) { $vn_next_more_pos += $vn_pos; $vs_partial_template = substr($vs_template, $vn_pos + strlen($va_more['directive']), $vn_next_more_pos - $vn_pos); } else { $vs_partial_template = substr($vs_template, $vn_pos + strlen($va_more['directive'])); } $vb_output = false; foreach (array_keys($va_defined_tag_list[$vn_i][$vn_j]) as $vs_defined_tag) { if (strpos($vs_partial_template, $vs_defined_tag) !== false) { // content is defined $vb_output = true; break; } } if ($vb_output) { $vs_template = preg_replace('!' . $va_more['directive'] . '!', $va_more['content'], $vs_template, 1); } else { $vs_template = preg_replace('!' . $va_more['directive'] . '!', '', $vs_template, 1); } } } // Process <between> tags - text to be output if it is between two defined values $va_between_positions = array(); foreach ($va_betweens as $vn_between_index => $va_between) { $vb_output_before = $vb_output_after = false; if (($vn_cur_pos = strpos($vs_template, $va_between['directive'])) !== false) { $va_between_positions[$vn_between_index] = $vn_cur_pos; // Get parts of template before tag and after tag $vs_partial_template_before = substr($vs_template, 0, $vn_cur_pos); $vs_partial_template_after = substr($vs_template, $vn_cur_pos + strlen($va_between['directive'])); // Only get the template between our current position and the next <between> tag if (isset($va_betweens[$vn_between_index + 1]) && ($vn_after_pos_relative = strpos($vs_partial_template_after, $va_betweens[$vn_between_index + 1]['directive'])) !== false) { $vs_partial_template_after = substr($vs_partial_template_after, 0, $vn_after_pos_relative); } // Check for defined value before and after tag foreach (array_keys($va_defined_tag_list[$vn_i][$vn_j]) as $vs_defined_tag) { if (strpos($vs_partial_template_before, $vs_defined_tag) !== false) { // content is defined $vb_output_after = true; } if (strpos($vs_partial_template_after, $vs_defined_tag) !== false) { // content is defined $vb_output_before = true; break; } if ($vb_output_before && $vb_output_after) { break; } } } if ($vb_output_before && $vb_output_after) { $vs_template = preg_replace('!' . $va_between['directive'] . '!', $va_between['content'], $vs_template, 1); } else { $vs_template = preg_replace('!' . $va_between['directive'] . '!', '', $vs_template, 1); } } // // Need to sort tags by length descending (longest first) // so that when we go to substitute and you have a tag followed by itself with a suffix // (ex. ^measurements and ^measurements2) we don't substitute both for the stub (ex. ^measurements) // $va_tags_tmp = array_keys($va_tags); usort($va_tags_tmp, function ($a, $b) { return strlen($b) - strlen($a); }); $vs_pt = $vs_template; foreach ($va_tags_tmp as $vs_tag) { $vs_pt = str_replace('^' . $vs_tag, is_array($va_tags[$vs_tag]) ? join(" | ", $va_tags[$vs_tag]) : $va_tags[$vs_tag], $vs_pt); } $va_pt_vals[] = $vs_pt; $va_acc[] = join(isset($pa_options['delimiter']) ? $pa_options['delimiter'] : $vs_delimiter, $va_pt_vals); } $va_proc_templates[$vn_i] = join($vs_delimiter, $va_acc); } foreach ($va_proc_templates as $vn_i => $vs_template) { if (!strlen(trim($vs_template))) { unset($va_proc_templates[$vn_i]); } } // Transform links $va_proc_templates = caCreateLinksFromText($va_proc_templates, $ps_resolve_links_using, $ps_resolve_links_using != $ps_tablename ? $va_resolve_links_using_row_ids : $pa_row_ids, null, null, $pa_options); // Kill any lingering tags (just in case) foreach ($va_proc_templates as $vn_i => $vs_proc_template) { $va_proc_templates[$vn_i] = preg_replace("!\\^([A-Za-z0-9_\\.]+[%]{1}[^ \\^\t\r\n\"\\'<>\\(\\)\\{\\}\\/\\[\\]]*|[A-Za-z0-9_\\.]+)!", "", $vs_proc_template); } if ($pb_return_as_array) { return $va_proc_templates; } return join($vs_delimiter, $va_proc_templates); }
/** * Implementation of primary get() functionality */ private function _get($ps_field, $pa_options = null) { if (!is_array($pa_options)) { $pa_options = array(); } if (isset($pa_options['restrictToType']) && (!isset($pa_options['restrict_to_type']) || !$pa_options['restrict_to_type'])) { $pa_options['restrict_to_type'] = $pa_options['restrictToType']; } if (isset($pa_options['restrictToTypes']) && (!isset($pa_options['restrict_to_types']) || !$pa_options['restrict_to_types'])) { $pa_options['restrict_to_types'] = $pa_options['restrictToTypes']; } if (isset($pa_options['restrictToRelationshipTypes']) && (!isset($pa_options['restrict_to_relationship_types']) || !$pa_options['restrict_to_relationship_types'])) { $pa_options['restrict_to_relationship_types'] = $pa_options['restrictToRelationshipTypes']; } if (isset($pa_options['excludeType']) && (!isset($pa_options['exclude_type']) || !$pa_options['exclude_type'])) { $pa_options['exclude_type'] = $pa_options['excludeType']; } if (isset($pa_options['excludeTypes']) && (!isset($pa_options['exclude_types']) || !$pa_options['exclude_types'])) { $pa_options['exclude_types'] = $pa_options['excludeTypes']; } if (isset($pa_options['excludeRelationshipTypes']) && (!isset($pa_options['exclude_relationship_types']) || !$pa_options['exclude_relationship_types'])) { $pa_options['exclude_relationship_types'] = $pa_options['excludeRelationshipTypes']; } $vb_return_as_array = caGetOption('returnAsArray', $pa_options, false, array('castTo' => 'bool')); $vb_return_all_locales = caGetOption('returnAllLocales', $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, ''); $vs_return_as_link_attributes = caGetOption('returnAsLinkAttributes', $pa_options, array(), array('castTo' => 'array')); $va_original_path_components = $va_path_components = $this->getFieldPathComponents($ps_field); 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 (caGetBundleAccessLevel($this->ops_table_name, $vs_access_chk_key) == __CA_BUNDLE_ACCESS_NONE__) { return null; } $vo_request = caGetOption('request', $pa_options, null); unset($pa_options['request']); // first see if the search engine can provide the field value directly (fastest) 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; } } $vs_template = caGetOption('template', $pa_options, null); $vs_delimiter = caGetOption('delimiter', $pa_options, ' '); $vs_hierarchical_delimiter = caGetOption('hierarchicalDelimiter', $pa_options, ' '); if ($vb_return_all_locales && !$vb_return_as_array) { $vb_return_as_array = true; } if (isset($pa_options['sort']) && !is_array($pa_options['sort'])) { $pa_options['sort'] = array($pa_options['sort']); } if (is_array($va_sort_fields = isset($pa_options['sort']) && is_array($pa_options['sort']) ? $pa_options['sort'] : null)) { foreach ($va_sort_fields as $vn_i => $vs_sort_fld) { if (!trim($vs_sort_fld)) { unset($va_sort_fields[$vn_i]); } } } $vn_row_id = $this->opo_engine_result->get($this->ops_table_pk); // try to lazy load (slower)... // // Are we getting timestamp (created on or last modified) info? // if ($va_path_components['table_name'] == $this->ops_table_name && $va_path_components['field_name'] == 'created') { if (!isset($this->opa_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) { return $this->opa_timestamp_cache['created_on'][$this->ops_table_name][$vn_row_id]; } else { $vs_subfield = $va_path_components['subfield_name'] ? $va_path_components['subfield_name'] : 'timestamp'; $vm_val = $this->opa_timestamp_cache['created_on'][$this->ops_table_name][$vn_row_id][$vs_subfield]; if ($vs_subfield == 'timestamp') { $o_tep = new TimeExpressionParser(); $o_tep->setUnixTimestamps($vm_val, $vm_val); $vm_val = $o_tep->getText($pa_options); } return $vm_val; } } if ($va_path_components['table_name'] == $this->ops_table_name && $va_path_components['field_name'] == 'lastModified') { if (!isset($this->opa_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) { return $this->opa_timestamp_cache['last_changed'][$this->ops_table_name][$vn_row_id]; } else { $vs_subfield = $va_path_components['subfield_name'] ? $va_path_components['subfield_name'] : 'timestamp'; $vm_val = $this->opa_timestamp_cache['last_changed'][$this->ops_table_name][$vn_row_id][$vs_subfield]; if ($vs_subfield == 'timestamp') { $o_tep = new TimeExpressionParser(); $o_tep->setUnixTimestamps($vm_val, $vm_val); $vm_val = $o_tep->getText($pa_options); } return $vm_val; } } if (!($t_instance = $this->opo_datamodel->getInstanceByTableName($va_path_components['table_name'], true))) { return null; } // Bad table $t_original_instance = $t_instance; // $t_original_instance will always be the as-called subject; optimizations may results in $t_instance being transformed into a different model // // Simple related table get: // <table> // <table>.related // <table>.hierarchy // <table>.related.hierarchy // if ($va_path_components['num_components'] == 1 && $va_path_components['table_name'] !== $this->ops_table_name || $va_path_components['num_components'] == 2 && $va_path_components['field_name'] == 'related' || $va_path_components['num_components'] == 2 && $va_path_components['field_name'] == 'hierarchy' || $va_path_components['num_components'] == 3 && $va_path_components['field_name'] == 'related' && $va_path_components['subfield_name'] == 'hierarchy') { if (!($t_table = $this->opo_datamodel->getInstanceByTableName($this->ops_table_name, true))) { return null; } $vb_show_hierarachy = (bool) ($va_path_components['field_name'] == 'hierarchy' && $t_instance->isHierarchical()); if ($va_path_components['num_components'] == 2) { $va_path_components['num_components'] = 1; $va_path_components['field_name'] = null; } $vs_opt_md5 = caMakeCacheKeyFromOptions($pa_options); if (!isset($this->opa_rel_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5])) { $this->prefetchRelated($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options); } $va_related_items = $this->opa_rel_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5]; if (!is_array($va_related_items)) { return null; } if (is_array($va_sort_fields) && sizeof($va_sort_fields)) { $va_related_items = caSortArrayByKeyInValue($va_related_items, $va_sort_fields); } // Return as array if ($vs_template) { return caProcessTemplateForIDs($vs_template, $this->opo_subject_instance->tableName(), array($vn_row_id), array_merge($pa_options, array('placeholderPrefix' => $va_path_components['field_name']))); } if ($vb_return_as_array || $vb_return_all_locales) { 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; } return $va_related_tmp; } else { if (!$vs_template && !$va_path_components['field_name']) { return $va_related_items; } $vs_pk = $t_instance->primaryKey(); $va_links = array(); foreach ($va_related_items as $vn_relation_id => $va_relation_info) { $va_relation_info['labels'] = caExtractValuesByUserLocale(array(0 => $va_relation_info['labels'])); if ($vb_return_as_link) { $va_template_opts = array(); $va_template_opts['relationshipValues'][$va_relation_info[$vs_pk]][$va_relation_info['relation_id']]['relationship_typename'] = $va_relation_info['relationship_typename']; $vs_text = $vs_template ? caProcessTemplateForIDs($vs_template, $t_instance->tableName(), array($va_relation_info[$vs_pk]), $va_template_opts) : join("; ", $va_relation_info['labels']); $va_link = caCreateLinksFromText(array($vs_text), $va_original_path_components['table_name'], array($va_relation_info[$vs_pk]), $vs_return_as_link_class, $vs_return_as_link_target); $va_links[$vn_relation_id] = array_pop($va_link); } else { $va_related_items[$vn_relation_id]['labels'] = $va_relation_info['labels']; } } if ($vb_return_as_link) { return $va_links; } return $va_related_items; } } else { // Return scalar $va_proc_labels = array(); $va_row_ids = array(); $vs_rel_pk = $t_instance->primaryKey(); $va_relationship_values = array(); foreach ($va_related_items as $vn_relation_id => $va_relation_info) { $va_row_ids[] = $va_relation_info[$vs_rel_pk]; $va_relationship_values[$va_relation_info[$vs_rel_pk]][$vn_relation_id] = array('relationship_typename' => $va_relation_info['relationship_typename'], 'relationship_type_id' => $va_relation_info['relationship_type_id'], 'relationship_type_code' => $va_relation_info['relationship_type_code'], 'relationship_typecode' => $va_relation_info['relationship_type_code'], 'label' => $va_relation_info['label']); } if (!sizeof($va_row_ids)) { return ''; } if (!$vs_template) { $vs_template = "^label"; } $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_text = caProcessTemplateForIDs($vs_template, $t_instance->tableNum(), $va_row_ids, array_merge($va_template_opts, array('relationshipValues' => $va_relationship_values, 'showHierarchicalLabels' => $vb_show_hierarachy))); if ($vb_return_as_link) { $va_links = caCreateLinksFromText($va_text, $va_original_path_components['table_name'], $va_row_ids, $vs_return_as_link_class, $vs_return_as_link_target); return join($vs_delimiter, $va_links); } return join($vs_delimiter, $va_text); } } $vb_need_parent = false; $vb_need_children = false; // // Transform "preferred_labels" into tables for pre-fetching // $vb_is_get_for_labels = $vb_return_all_label_values = $vb_get_preferred_labels_only = $vb_get_nonpreferred_labels_only = false; if (in_array($va_path_components['field_name'], array('preferred_labels', 'nonpreferred_labels'))) { if ($t_instance->getProperty('LABEL_TABLE_NAME')) { $vb_get_preferred_labels_only = $va_path_components['field_name'] == 'preferred_labels' ? true : false; $vb_get_nonpreferred_labels_only = $va_path_components['field_name'] == 'nonpreferred_labels' ? true : false; if ($va_path_components['num_components'] == 2) { // if it's just <table_name>.preferred_labels then return an array of fields from the label table $vb_return_all_label_values = true; } $va_path_components['table_name'] = $t_instance->getLabelTableName(); $t_label_instance = $t_instance->getLabelTableInstance(); if (!$va_path_components['subfield_name'] || !$t_label_instance->hasField($va_path_components['subfield_name'])) { $va_path_components['field_name'] = $t_instance->getLabelDisplayField(); } else { $va_path_components['field_name'] = $va_path_components['subfield_name']; } $va_path_components['subfield_name'] = null; $va_path_components = $this->getFieldPathComponents($va_path_components['table_name'] . '.' . $va_path_components['field_name']); // Ok, convert the table instance to the label table since that's the table we'll be grabbing data from $t_instance = $t_label_instance; $vb_is_get_for_labels = true; } } // // Handle modifiers (parent, children, related, hierarchy) with and without fields // if ($va_path_components['num_components'] >= 2) { switch ($va_path_components['field_name']) { case 'parent': if ($t_instance->isHierarchical() && ($vn_parent_id = $this->get($va_path_components['table_name'] . '.' . $t_instance->getProperty('HIERARCHY_PARENT_ID_FLD')))) { // // TODO: support some kind of prefetching of parents? // unset($va_path_components['components'][1]); if ($t_instance->load($vn_parent_id)) { return $t_instance->get(join('.', array_values($va_path_components['components'])), $pa_options); } return null; } break; case 'children': if ($t_instance->isHierarchical()) { //unset($va_path_components['components'][1]); // remove 'children' from field path $vs_field_spec = join('.', array_values($va_path_components['components'])); if ($vn_id = $this->get($va_path_components['table_name'] . '.' . $t_instance->primaryKey(), array('returnAsArray' => false))) { if ($t_instance->load($vn_id)) { return $t_instance->get($vs_field_spec, $pa_options); } } return null; } break; case 'related': // Regular related table call if ($va_path_components['table_name'] != $this->ops_table_name) { // just remove "related" from name and be on our way $va_tmp = $va_path_components['components']; array_splice($va_tmp, 1, 1); return $this->get(join('.', $va_tmp), $pa_options); } // Self-relations need special handling $vs_opt_md5 = caMakeCacheKeyFromOptions($pa_options); if (!isset($this->opa_rel_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5])) { $this->prefetchRelated($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options); } $va_related_items = $this->opa_rel_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5]; if (!($t_table = $this->opo_datamodel->getInstanceByTableName($va_path_components['table_name'], true))) { return null; } $va_ids = array(); foreach ($va_related_items as $vn_relation_id => $va_item) { $va_ids[] = $va_item[$t_table->primaryKey()]; } $va_vals = array(); if ($qr_res = $t_table->makeSearchResult($va_path_components['table_name'], $va_ids)) { $va_tmp = $va_path_components['components']; unset($va_tmp[1]); $vs_rel_field = join('.', $va_tmp); while ($qr_res->nextHit()) { if ($vb_return_as_array) { $va_vals = array_merge($va_vals, $qr_res->get($vs_rel_field, $pa_options)); } else { $va_vals[] = $qr_res->get($vs_rel_field, $pa_options); } } } //if (is_array($va_sort_fields) && sizeof($va_sort_fields)) { // $va_vals = caSortArrayByKeyInValue($va_vals, $va_sort_fields); //} if ($vb_return_as_link) { if (!$vb_return_all_locales) { $va_vals = caCreateLinksFromText($va_vals, $va_original_path_components['table_name'], $va_ids, $vs_return_as_link_class, $vs_return_as_link_target); } } if ($vb_return_as_array) { return $va_vals; } else { return join($vs_delimiter, $va_vals); } break; case 'hierarchy': $vn_max_levels_from_bottom = caGetOption('maxLevelsFromBottom', $pa_options, caGetOption('maxLevels', $pa_options, null)); $vn_max_levels_from_top = caGetOption('maxLevelsFromTop', $pa_options, null); if ($t_instance->isHierarchical()) { $vs_field_spec = join('.', array_values($va_path_components['components'])); $vs_hier_pk_fld = $t_instance->primaryKey(); if ($va_ids = $this->get($va_path_components['table_name'] . '.' . $vs_hier_pk_fld, array_merge($pa_options, array('returnAsArray' => true, 'returnAsLink' => false, 'returnAllLocales' => false)))) { $va_vals = array(); if ($va_path_components['subfield_name'] == $vs_hier_pk_fld) { foreach ($va_ids as $vn_id) { // TODO: This is too slow if ($t_instance->load($vn_id)) { $va_vals = array_merge($va_vals, $t_instance->get($va_path_components['table_name'] . ".hierarchy." . $vs_hier_pk_fld, array_merge($pa_options, array('returnAsArray' => true)))); } } } else { foreach ($va_ids as $vn_id) { // TODO: This is too slow if ($t_instance->load($vn_id)) { $va_vals = $t_instance->get($vs_field_spec, array_merge($pa_options, array('returnAsArray' => true))); if (is_array($va_vals)) { $va_vals = array_reverse($va_vals); } // Add/replace hierarchy name if ($t_instance->getProperty('HIERARCHY_TYPE') == __CA_HIER_TYPE_MULTI_MONO__ && $t_instance->getHierarchyName()) { $vn_first_key = array_shift(array_keys($va_vals)); if ($vb_return_all_locales) { $va_vals[$vn_first_key] = array(0 => array($t_instance->getHierarchyName())); } else { $va_vals[$vn_first_key] = $t_instance->getHierarchyName(); } } if ($vn_max_levels_from_bottom > 0) { if (($vn_start = sizeof($va_vals) - $vn_max_levels_from_bottom) < 0) { $vn_start = 0; } $va_vals = array_slice($va_vals, $vn_start, $vn_max_levels_from_bottom, true); } elseif ($vn_max_levels_from_top > 0) { $va_vals = array_slice($va_vals, 0, $vn_max_levels_from_top, true); } } } } if ($vb_return_as_array) { return $va_vals; } else { return join($vs_hierarchical_delimiter, $va_vals); } } return null; } break; } } // If the requested table was not added to the query via SearchEngine::addTable() // then auto-add it here. It's better to explicitly add it with addTables() as that call // gives you precise control over which fields are autoloaded and also lets you specify limiting criteria // for selection of related field data; and it also lets you explicitly define the tables used to join the // related table. Autoloading guesses and usually does what you want, but not always. if (!isset($this->opa_tables[$va_path_components['table_name']]) || !$this->opa_tables[$va_path_components['table_name']]) { $va_join_tables = $this->opo_datamodel->getPath($this->ops_table_name, $va_path_components['table_name']); array_shift($va_join_tables); // remove subject table array_pop($va_join_tables); // remove content table (we only need linking tables here) $va_join_criteria = array(); if (is_array($va_primary_ids)) { foreach ($va_primary_ids as $vs_t => $va_t_ids) { if (isset($va_join_tables[$vs_t]) && sizeof($va_t_ids) > 0) { $vs_t_pk = $this->opo_datamodel->getTablePrimaryKeyName($vs_t); $va_join_criteria[] = "{$vs_t}.{$vs_t_pk} NOT IN (" . join(",", $va_t_ids) . ")"; } } } $this->opa_tables[$va_path_components['table_name']] = array('fieldList' => array($va_path_components['table_name'] . '.*'), 'joinTables' => array_keys($va_join_tables), 'criteria' => $va_join_criteria); } if ($va_path_components['table_name'] === $this->ops_table_name && !$t_instance->hasField($va_path_components['field_name']) && method_exists($t_instance, 'getAttributes')) { // // Return attribute values for primary table // if ($va_path_components['field_name'] && ($t_element = $t_instance->_getElementInstance($va_path_components['field_name']))) { $vn_element_id = $t_element->getPrimaryKey(); } else { $vn_element_id = null; } if (!isset(ca_attributes::$s_get_attributes_cache[$this->opn_table_num . '/' . $vn_row_id][$vn_element_id])) { ca_attributes::prefetchAttributes($this->opo_db, $this->opn_table_num, $this->getRowIDsToPrefetch($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch')), $vn_element_id ? array($vn_element_id) : null, array('dontFetchAlreadyCachedValues' => true)); } if (!$vb_return_as_array && !$vb_return_all_locales) { // return scalar // // Handle "hierarchy" modifier on list elements // if ($va_hier = $this->_getElementHierarchy($t_instance, $va_path_components)) { return join($vs_hierarchical_delimiter, $va_hier); } if (isset($pa_options['convertCodesToDisplayText']) && $pa_options['convertCodesToDisplayText'] && $va_path_components['field_name']) { $vs_template = null; if ($va_path_components['subfield_name']) { $va_values = $t_instance->getAttributeDisplayValues($va_path_components['field_name'], $vn_row_id, $pa_options); $va_value_list = array(); foreach ($va_values as $vn_id => $va_attr_val_list) { foreach ($va_attr_val_list as $vn_value_id => $va_value_array) { $va_value_list[] = $va_value_array[$va_path_components['subfield_name']]; } } return join(" ", $va_value_list); } else { if (isset($pa_options['template'])) { $vs_template = $pa_options['template']; } } unset($pa_options['template']); if (!$vs_template) { $vs_template = "^" . $va_path_components['subfield_name'] ? $va_path_components['subfield_name'] : $va_path_components['field_name']; } return $t_instance->getAttributesForDisplay($va_path_components['field_name'], $vs_template, array_merge(array('row_id' => $vn_row_id), $pa_options)); } if ($t_element && !$va_path_components['subfield_name'] && $t_element->get('datatype') == 0) { return $t_instance->getAttributesForDisplay($va_path_components['field_name'], $vs_template, array_merge($pa_options, array('row_id' => $vn_row_id))); } else { if (!$vs_template) { return $t_instance->getRawValue($vn_row_id, $va_path_components['field_name'], $va_path_components['subfield_name'], ',', $pa_options); } else { return caProcessTemplateForIDs($vs_template, $va_path_components['table_name'], array($vn_row_id), array()); } } } else { // return array // // Handle "hierarchy" modifier on list elements // if ($va_hier = $this->_getElementHierarchy($t_instance, $va_path_components)) { return $va_hier; } $va_values = $t_instance->getAttributeDisplayValues($va_path_components['field_name'], $vn_row_id, $pa_options); if ($vs_template && !$vb_return_all_locales) { $va_values_tmp = array(); foreach ($va_values as $vn_i => $va_value_list) { foreach ($va_value_list as $vn_attr_id => $va_attr_data) { $va_values_tmp[] = caProcessTemplateForIDs($vs_template, $va_path_components['table_name'], array($vn_row_id), array_merge($pa_options, array('placeholderPrefix' => $va_path_components['field_name']))); } } $va_values = $va_values_tmp; } else { if ($va_path_components['subfield_name']) { if ($vb_return_all_locales) { foreach ($va_values as $vn_row_id => $va_values_by_locale) { foreach ($va_values_by_locale as $vn_locale_id => $va_value_list) { foreach ($va_value_list as $vn_attr_id => $va_attr_data) { $va_values[$vn_row_id][$vn_locale_id][$vn_attr_id] = $va_attr_data[$va_path_components['subfield_name']]; } } } } else { $va_processed_value_list = array(); foreach ($va_values as $vn_row_id => $va_value_list) { foreach ($va_value_list as $vn_attr_id => $va_attr_data) { $va_processed_value_list[$vn_attr_id] = $va_attr_data[$va_path_components['subfield_name']]; } } $va_values = $va_processed_value_list; } } else { if (!$vb_return_all_locales) { $va_values = array_shift($va_values); } } } return $va_values; } } else { // Prefetch intrinsic fields in primary and related tables if (!isset($this->opa_prefetch_cache[$va_path_components['table_name']][$vn_row_id])) { $this->prefetch($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options); // try to prefetch ahead (usually doesn't hurt and very often helps performance) } } $va_return_values = array(); if ($va_path_components['table_name'] !== $this->ops_table_name && $va_path_components['field_name'] !== 'relationship_typename' && !$t_instance->hasField($va_path_components['field_name']) && method_exists($t_instance, 'getAttributes')) { // // Return metadata attributes in a related table // $vs_pk = $t_instance->primaryKey(); $vb_is_related = $this->ops_table_name !== $va_path_components['table_name']; $va_ids = array(); $vs_opt_md5 = caMakeCacheKeyFromOptions($pa_options); if (!isset($this->opa_rel_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5])) { $this->prefetchRelated($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options); } if (is_array($this->opa_rel_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5])) { foreach ($this->opa_rel_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5] as $vn_i => $va_values) { //$vn_locale_id => $va_values_by_locale) { $va_ids[] = $va_values[$vs_pk]; if (!$vb_return_as_array) { $vs_val = $t_instance->getAttributesForDisplay($va_path_components['field_name'], $vs_template, array_merge(array('row_id' => $va_values[$vs_pk]), $pa_options)); } else { $vs_val = $t_instance->getAttributeDisplayValues($va_path_components['field_name'], $va_values[$vs_pk], $pa_options); } if ($vs_val) { if ($vb_return_as_array) { if (!$vb_return_all_locales) { foreach ($vs_val as $vn_i => $va_values_list) { foreach ($va_values_list as $vn_j => $va_values) { $va_return_values[] = $va_values; } } } else { foreach ($vs_val as $vn_i => $va_values_list) { $va_return_values[] = $va_values_list; } } } else { $va_return_values[] = $vs_val; } } } } if ($vb_return_as_array || $vb_return_all_locales) { // return array if ($vb_return_as_link && $vb_is_related) { $vs_table_name = $t_instance->tableName(); $vs_fld_key = $va_path_components['subfield_name'] ? $va_path_components['subfield_name'] : $va_path_components['field_name']; if (!$vb_return_all_locales) { $va_return_values_tmp = array(); foreach ($va_return_values as $vn_i => $va_value) { if ($vs_template) { $vs_value = caProcessTemplateForIDs($vs_template, $va_path_components['table_name'], array($va_ids[$vn_i][$vs_pk]), array('returnAsArray' => false)); } else { $vs_value = $va_value[$vs_fld_key]; } if ($vb_return_as_link) { $va_return_values_tmp[$vn_i] = array_pop(caCreateLinksFromText(array($vs_value), $va_original_path_components['table_name'], array($va_ids[$vn_i]), $vs_return_as_link_class, $vs_return_as_link_target)); } else { $va_return_values_tmp[$vn_i] = $vs_value; } } $va_return_values = $va_return_values_tmp; } } return $va_return_values; } else { // return scalar if ($vb_return_as_link && $vb_is_related) { $va_return_values = caCreateLinksFromText($va_return_values, $va_original_path_components['table_name'], $va_ids, $vs_return_as_link_class, $vs_return_as_link_target); } if (isset($pa_options['convertLineBreaks']) && $pa_options['convertLineBreaks']) { return caConvertLineBreaks(join($vs_delimiter, $va_return_values)); } else { return join($vs_delimiter, $va_return_values); } } } else { if ($vs_template) { return caProcessTemplateForIDs($vs_template, $this->opo_subject_instance->tableName(), array($vn_row_id), array_merge($pa_options, array('placeholderPrefix' => $va_path_components['field_name']))); } // // Return fields (intrinsics, labels) in primary or related table // $t_list = $this->opo_datamodel->getInstanceByTableName('ca_lists', true); $va_value_list = array($vn_row_id => $this->opa_prefetch_cache[$va_path_components['table_name']][$vn_row_id]); // Restrict to relationship types (related) if (isset($pa_options['restrict_to_relationship_types']) && $pa_options['restrict_to_relationship_types']) { if (!is_array($pa_options['restrict_to_relationship_types'])) { $pa_options['restrict_to_relationship_types'] = array($pa_options['restrict_to_relationship_types']); } if (sizeof($pa_options['restrict_to_relationship_types'])) { $t_rel_type = $this->opo_datamodel->getInstanceByTableName('ca_relationship_types', true); $va_rel_types = array(); $va_rel_path = array_keys($this->opo_datamodel->getPath($this->ops_table_name, $va_path_components['table_name'])); foreach ($pa_options['restrict_to_relationship_types'] as $vm_type) { if (!$vm_type) { continue; } if ($vn_type_id = $t_rel_type->getRelationshipTypeID($va_rel_path[1], $vm_type)) { $va_rel_types[] = $vn_type_id; if (is_array($va_children = $t_rel_type->getHierarchyChildren($vn_type_id, array('idsOnly' => true)))) { $va_rel_types = array_merge($va_rel_types, $va_children); } } } if (sizeof($va_rel_types)) { $va_tmp = array(); foreach ($va_value_list as $vn_id => $va_by_locale) { foreach ($va_by_locale as $vn_locale_id => $va_values) { foreach ($va_values as $vn_i => $va_value) { if (!$va_value['rel_type_id'] || in_array($va_value['rel_type_id'], $va_rel_types)) { $va_tmp[$vn_id][$vn_locale_id][$vn_i] = $va_value; } } } } $va_value_list = $va_tmp; } } } // Exclude relationship types (related) if (isset($pa_options['exclude_relationship_types']) && $pa_options['exclude_relationship_types']) { if (!is_array($pa_options['exclude_relationship_types'])) { $pa_options['exclude_relationship_types'] = array($pa_options['exclude_relationship_types']); } if (sizeof($pa_options['exclude_relationship_types'])) { $t_rel_type = $this->opo_datamodel->getInstanceByTableName('ca_relationship_types', true); $va_rel_types = array(); $va_rel_path = array_keys($this->opo_datamodel->getPath($this->ops_table_name, $va_path_components['table_name'])); foreach ($pa_options['exclude_relationship_types'] as $vm_type) { if ($vn_type_id = $t_rel_type->getRelationshipTypeID($va_rel_path[1], $vm_type)) { $va_rel_types[] = $vn_type_id; if (is_array($va_children = $t_rel_type->getHierarchyChildren($vn_type_id, array('idsOnly' => true)))) { $va_rel_types = array_merge($va_rel_types, $va_children); } } } if (sizeof($va_rel_types)) { $va_tmp = array(); foreach ($va_value_list as $vn_id => $va_by_locale) { foreach ($va_by_locale as $vn_locale_id => $va_values) { foreach ($va_values as $vn_i => $va_value) { if (!in_array($va_value['rel_type_id'], $va_rel_types)) { $va_tmp[$vn_id][$vn_locale_id][$vn_i] = $va_value; } } } } $va_value_list = $va_tmp; } } } // Restrict to types (related) $va_type_ids = $vs_type_fld = null; if (method_exists($t_instance, "getTypeFieldName")) { $va_type_ids = caMergeTypeRestrictionLists($t_instance, $pa_options); $vs_type_fld = $t_instance->getTypeFieldName(); } else { if (method_exists($t_instance, "getSubjectTableInstance")) { $t_label_subj_instance = $t_instance->getSubjectTableInstance(); if (method_exists($t_label_subj_instance, "getTypeFieldName")) { $va_type_ids = caMergeTypeRestrictionLists($t_label_subj_instance, $pa_options); $vs_type_fld = 'item_type_id'; } } } if (is_array($va_type_ids) && sizeof($va_type_ids)) { $va_tmp = array(); foreach ($va_value_list as $vn_id => $va_by_locale) { foreach ($va_by_locale as $vn_locale_id => $va_values) { foreach ($va_values as $vn_i => $va_value) { if (!$va_value[$vs_type_fld ? $vs_type_fld : 'item_type_id'] || in_array($va_value[$vs_type_fld ? $vs_type_fld : 'item_type_id'], $va_type_ids)) { $va_tmp[$vn_id][$vn_locale_id][$vn_i] = $va_value; } } } } $va_value_list = $va_tmp; } // Restrict to sources (related) $va_source_ids = $vs_source_id_fld = null; if (method_exists($t_instance, "getSourceFieldName")) { $va_source_ids = caMergeSourceRestrictionLists($t_instance, $pa_options); $vs_source_id_fld = $t_instance->getSourceFieldName(); } else { if (method_exists($t_instance, "getSubjectTableInstance")) { $t_label_subj_instance = $t_instance->getSubjectTableInstance(); if (method_exists($t_label_subj_instance, "getSourceFieldName")) { $va_source_ids = caMergeSourceRestrictionLists($t_label_subj_instance, $pa_options); $vs_source_id_fld = 'item_source_id'; } } } if (is_array($va_source_ids) && sizeof($va_source_ids)) { $va_tmp = array(); foreach ($va_value_list as $vn_id => $va_by_locale) { foreach ($va_by_locale as $vn_locale_id => $va_values) { foreach ($va_values as $vn_i => $va_value) { if (!$va_value[$vs_source_id_fld ? $vs_source_id_fld : 'item_source_id'] || in_array($va_value[$vs_source_id_fld ? $vs_source_id_fld : 'item_source_id'], $va_source_ids)) { $va_tmp[$vn_id][$vn_locale_id][$vn_i] = $va_value; } } } } $va_value_list = $va_tmp; } // Exclude types (related) if (isset($pa_options['exclude_type']) && $pa_options['exclude_type']) { if (!isset($pa_options['exclude_types']) || !is_array($pa_options['exclude_types'])) { $pa_options['exclude_types'] = array(); } $pa_options['exclude_types'][] = $pa_options['exclude_type']; } if (isset($pa_options['exclude_types']) && is_array($pa_options['exclude_types'])) { $va_ids = caMakeTypeIDList($va_path_components['table_name'], $pa_options['exclude_types']); if (is_array($va_ids) && sizeof($va_ids) > 0) { $va_tmp = array(); foreach ($va_value_list as $vn_id => $va_by_locale) { foreach ($va_by_locale as $vn_locale_id => $va_values) { foreach ($va_values as $vn_i => $va_value) { if (!in_array($va_value[$vs_type_fld ? $vs_type_fld : 'item_type_id'], $va_type_ids)) { $va_tmp[$vn_id][$vn_locale_id][$vn_i] = $va_value; } } } } $va_value_list = $va_tmp; } } // Handle 'relationship_typename' (related) $vb_get_relationship_typename = false; if ($va_path_components['field_name'] == 'relationship_typename') { $va_path_components['field_name'] = 'rel_type_id'; $vb_get_relationship_typename = true; } if ($vb_return_as_array) { // return array (intrinsics or labels in primary or related table) if ($t_instance->hasField($va_path_components['field_name']) && $va_path_components['table_name'] === $t_instance->tableName()) { // Intrinsic $va_field_info = $t_instance->getFieldInfo($va_path_components['field_name']); $vs_pk = $t_original_instance->primaryKey(); // Handle specific intrinsic types switch ($va_field_info['FIELD_TYPE']) { case FT_DATERANGE: case FT_HISTORIC_DATERANGE: foreach ($va_value_list as $vn_id => $va_values_by_locale) { foreach ($va_values_by_locale as $vn_locale_id => $va_values) { foreach ($va_values as $vn_i => $va_value) { $va_ids[] = $va_value[$vs_pk]; if (caGetOption('GET_DIRECT_DATE', $pa_options, false) || caGetOption('getDirectDate', $pa_options, false)) { if (caGetOption('sortable', $pa_options, false)) { $vs_prop = $va_value[$va_field_info['START']] . '/' . $va_value[$va_field_info['END']]; } else { $vs_prop = $va_value[$va_field_info['START']]; } } else { $this->opo_tep->init(); if ($va_field_info['FIELD_TYPE'] == FT_DATERANGE) { $this->opo_tep->setUnixTimestamps($va_value[$va_field_info['START']], $va_value[$va_field_info['END']]); } else { $this->opo_tep->setHistoricTimestamps($va_value[$va_field_info['START']], $va_value[$va_field_info['END']]); } $vs_prop = $this->opo_tep->getText($pa_options); } if ($vb_return_all_locales) { $va_return_values[$vn_row_id][$vn_locale_id][] = $vs_prop; } else { $va_return_values[] = $vs_prop; } } } } break; case FT_MEDIA: if (!($vs_version = $va_path_components['subfield_name'])) { $vs_version = "largeicon"; } foreach ($va_value_list as $vn_id => $va_values_by_locale) { foreach ($va_values_by_locale as $vn_locale_id => $va_values) { foreach ($va_values as $vn_i => $va_value) { $va_ids[] = $va_value[$vs_pk]; if (isset($pa_options['unserialize']) && $pa_options['unserialize']) { $vs_prop = caUnserializeForDatabase($va_value[$va_path_components['field_name']]); if ($vb_return_all_locales) { $va_return_values[$vn_row_id][$vn_locale_id][] = $vs_prop; } else { $va_return_values[] = $vs_prop; } } else { $o_media_settings = new MediaProcessingSettings($va_path_components['table_name'], $va_path_components['field_name']); $va_versions = $o_media_settings->getMediaTypeVersions('*'); if (!isset($va_versions[$vs_version])) { $va_tmp = array_keys($va_versions); $vs_version = array_shift($va_tmp); } // See if an info element was passed, eg. ca_object_representations.media.icon.width should return the width of the media rather than a tag or url to the media $vs_info_element = $va_path_components['num_components'] == 4 ? $va_path_components['components'][3] : null; if ($vb_return_all_locales) { if ($vs_info_element) { $va_return_values[$vn_row_id][$vn_locale_id][] = $this->getMediaInfo($va_path_components['table_name'] . '.' . $va_path_components['field_name'], $vs_version, $vs_info_element, $pa_options); } elseif (isset($pa_options['returnURL']) && $pa_options['returnURL']) { $va_return_values[$vn_row_id][$vn_locale_id][] = $this->getMediaUrl($va_path_components['table_name'] . '.' . $va_path_components['field_name'], $vs_version, $pa_options); } else { $va_return_values[$vn_row_id][$vn_locale_id][] = $this->getMediaTag($va_path_components['table_name'] . '.' . $va_path_components['field_name'], $vs_version, $pa_options); } } else { if ($vs_info_element) { $va_return_values[] = $this->getMediaInfo($va_path_components['table_name'] . '.' . $va_path_components['field_name'], $vs_version, $vs_info_element, $pa_options); } elseif (isset($pa_options['returnURL']) && $pa_options['returnURL']) { $va_return_values[] = $this->getMediaUrl($va_path_components['table_name'] . '.' . $va_path_components['field_name'], $vs_version, $pa_options); } else { $va_return_values[] = $this->getMediaTag($va_path_components['table_name'] . '.' . $va_path_components['field_name'], $vs_version, $pa_options); } } } } } } break; default: // is intrinsic field in primary table $vb_supports_preferred = (bool) $t_instance->hasField('is_preferred'); foreach ($va_value_list as $vn_id => $va_values_by_locale) { foreach ($va_values_by_locale as $vn_locale_id => $va_values) { foreach ($va_values as $vn_i => $va_value) { $va_ids[] = $vn_id = $va_value[$vs_pk]; if ($vb_get_preferred_labels_only && $vb_supports_preferred && !$va_value['is_preferred']) { continue; } if ($vb_get_nonpreferred_labels_only && $vb_supports_preferred && $va_value['is_preferred']) { continue; } $vs_prop = $va_value[$va_path_components['field_name']]; if (isset($pa_options['convertCodesToDisplayText']) && $pa_options['convertCodesToDisplayText'] && ($vs_list_code = $t_instance->getFieldInfo($va_path_components['field_name'], "LIST_CODE"))) { $vs_prop = $t_list->getItemFromListForDisplayByItemID($vs_list_code, $vs_prop); } else { if (isset($pa_options['convertCodesToDisplayText']) && $pa_options['convertCodesToDisplayText'] && ($vs_list_code = $t_instance->getFieldInfo($va_path_components['field_name'], "LIST"))) { $vs_prop = $t_list->getItemFromListForDisplayByItemValue($vs_list_code, $vs_prop); } else { if (isset($pa_options['convertCodesToDisplayText']) && $pa_options['convertCodesToDisplayText'] && $va_path_components['field_name'] === 'locale_id' && (int) $vs_prop > 0) { $t_locale = new ca_locales($vs_prop); $vs_prop = $t_locale->getName(); } else { if (isset($pa_options['convertCodesToDisplayText']) && $pa_options['convertCodesToDisplayText'] && is_array($va_list = $t_instance->getFieldInfo($va_path_components['field_name'], "BOUNDS_CHOICE_LIST"))) { foreach ($va_list as $vs_option => $vs_value) { if ($vs_value == $vs_prop) { $vs_prop = $vs_option; break; } } } } } } if ($vb_return_all_locales) { $va_return_values[$vn_id][$vn_locale_id][] = $vs_prop; } else { $va_return_values[$vn_id][$vn_locale_id] = $vs_prop; } } } } if (!$vb_return_all_locales) { $va_return_values = array_values(caExtractValuesByUserLocale($va_return_values)); } break; } } else { // Attributes $vs_pk = $t_original_instance->primaryKey(); $vb_is_related = $this->ops_table_name !== $va_path_components['table_name']; $va_ids = array(); $t_instance = $this->opo_datamodel->getInstanceByTableName($va_path_components['table_name'], true); foreach ($va_value_list as $vn_i => $va_values_by_locale) { foreach ($va_values_by_locale as $vn_locale_id => $va_values) { foreach ($va_values as $vn_i => $va_value) { if ($vb_is_related) { $va_ids[] = $va_value[$vs_pk]; } if ($vb_get_preferred_labels_only && !$va_value['is_preferred']) { continue; } if ($vb_get_nonpreferred_labels_only && $va_value['is_preferred']) { continue; } // do we need to translate foreign key and choice list codes to display text? $vs_prop = $vb_return_all_label_values && !$vb_return_as_link ? $va_value : $va_value[$va_path_components['field_name']]; if ($vb_get_relationship_typename) { if (!$t_rel_type) { $t_rel_type = $this->opo_datamodel->getInstanceByTableName('ca_relationship_types', true); } if (is_array($va_labels = $t_rel_type->getDisplayLabels(false, array('row_id' => (int) $vs_prop)))) { $va_label = array_shift($va_labels); $vs_prop = $va_label[0]['typename']; } else { $vs_prop = "?"; } } else { // Decode list items to text if (isset($pa_options['convertCodesToDisplayText']) && $pa_options['convertCodesToDisplayText'] && ($vs_list_code = $t_instance->getFieldInfo($va_path_components['field_name'], "LIST_CODE"))) { $vs_prop = $t_list->getItemFromListForDisplayByItemID($vs_list_code, $vs_prop); } else { if (isset($pa_options['convertCodesToDisplayText']) && $pa_options['convertCodesToDisplayText'] && ($vs_list_code = $t_instance->getFieldInfo($va_path_components['field_name'], "LIST"))) { $vs_prop = $t_list->getItemFromListForDisplayByItemValue($vs_list_code, $vs_prop); } else { if (isset($pa_options['convertCodesToDisplayText']) && $pa_options['convertCodesToDisplayText'] && $va_path_components['field_name'] === 'locale_id' && (int) $vs_prop > 0) { $t_locale = new ca_locales($vs_prop); $vs_prop = $t_locale->getName(); } else { if (isset($pa_options['convertCodesToDisplayText']) && $pa_options['convertCodesToDisplayText'] && is_array($va_list = $t_instance->getFieldInfo($va_path_components['field_name'], "BOUNDS_CHOICE_LIST"))) { foreach ($va_list as $vs_option => $vs_value) { if ($vs_value == $vs_prop) { $vs_prop = $vs_option; break; } } } } } } } if ($vb_return_all_locales) { $va_return_values[$vn_row_id][$vn_locale_id][] = $vs_prop; } else { if ($vb_get_nonpreferred_labels_only && is_array($vs_prop)) { // non-preferred labels are lists of lists because they can repeat $va_return_values[][] = $vs_prop; } else { $va_return_values[] = $vs_prop; } } } } } } if ($vb_return_as_link) { if (!$vb_return_all_locales) { $va_return_values = caCreateLinksFromText($va_return_values, $va_original_path_components['table_name'], $va_ids, $vs_return_as_link_class, $vs_return_as_link_target); } } return $va_return_values; } else { // Return scalar (intrinsics or labels in primary or related table) if ($vb_get_preferred_labels_only || $vb_get_nonpreferred_labels_only) { // We have to distinguish between preferred and non-preferred labels here // so that only appropriate labels are passed for output. $va_filtered_values = array(); foreach ($va_value_list as $vn_label_id => $va_labels_by_locale) { foreach ($va_labels_by_locale as $vn_locale_id => $va_labels) { foreach ($va_labels as $vn_i => $va_label) { if ($vb_get_preferred_labels_only && (!isset($va_label['is_preferred']) || $va_label['is_preferred']) || $vb_get_nonpreferred_labels_only && !$va_label['is_preferred']) { $va_filtered_values[$vn_label_id][$vn_locale_id][] = $va_label; } } } } $va_value_list = $va_filtered_values; } $va_value_list = caExtractValuesByUserLocale($va_value_list); // do we need to translate foreign key and choice list codes to display text? $t_instance = $this->opo_datamodel->getInstanceByTableName($va_path_components['table_name'], true); $va_field_info = $t_instance->getFieldInfo($va_path_components['field_name']); $vs_pk = $t_instance->primaryKey(); $vb_is_related = $this->ops_table_name !== $va_path_components['table_name']; $va_ids = array(); foreach ($va_value_list as $vn_i => $va_values) { if (!is_array($va_values)) { continue; } // Handle specific intrinsic types $vs_template_value = $vs_template; foreach ($va_values as $vn_j => $va_value) { switch ($va_field_info['FIELD_TYPE']) { case FT_BIT: if ($pa_options['convertCodesToDisplayText']) { $va_value[$va_path_components['field_name']] = (bool) $vs_prop ? _t('yes') : _t('no'); } break; case FT_DATERANGE: if (caGetOption('GET_DIRECT_DATE', $pa_options, false) || caGetOption('getDirectDate', $pa_options, false)) { if (isset($pa_options['sortable']) && $pa_options['sortable']) { $va_value[$va_path_components['field_name']] = $va_value[$va_field_info['START']] . '/' . $va_value[$va_field_info['END']]; } else { $va_value[$va_path_components['field_name']] = $va_value[$va_field_info['START']]; } } else { $this->opo_tep->init(); $this->opo_tep->setUnixTimestamps($va_value[$va_field_info['START']], $va_value[$va_field_info['END']]); $va_value[$va_path_components['field_name']] = $this->opo_tep->getText($pa_options); } break; case FT_HISTORIC_DATERANGE: if (caGetOption('GET_DIRECT_DATE', $pa_options, false) || caGetOption('getDirectDate', $pa_options, false)) { if (caGetOption('sortable', $pa_options, false)) { $va_value[$va_path_components['field_name']] = $va_value[$va_field_info['START']] . '/' . $va_value[$va_field_info['END']]; } else { $va_value[$va_path_components['field_name']] = $va_value[$va_field_info['START']]; } } else { $this->opo_tep->init(); $this->opo_tep->setHistoricTimestamps($va_value[$va_field_info['START']], $va_value[$va_field_info['END']]); $va_value[$va_path_components['field_name']] = $this->opo_tep->getText($pa_options); } break; case FT_MEDIA: if (!($vs_version = $va_path_components['subfield_name'])) { $vs_version = "largeicon"; } // See if an info element was passed, eg. ca_object_representations.media.icon.width should return the width of the media rather than a tag or url to the media $vs_info_element = $va_path_components['num_components'] == 4 ? $va_path_components['components'][3] : null; if (isset($pa_options['unserialize']) && $pa_options['unserialize']) { return caUnserializeForDatabase($va_value[$va_path_components['field_name']]); } else { $o_media_settings = new MediaProcessingSettings($va_path_components['table_name'], $va_path_components['field_name']); $va_versions = $o_media_settings->getMediaTypeVersions('*'); if (!isset($va_versions[$vs_version])) { $va_tmp = array_keys($va_versions); $vs_version = array_shift($va_tmp); } if ($vs_info_element) { // Return media info $va_value[$va_path_components['field_name']] = $this->getMediaInfo($va_path_components['table_name'] . '.' . $va_path_components['field_name'], $vs_version, $vs_info_element, $pa_options); } elseif (isset($pa_options['returnURL']) && $pa_options['returnURL']) { $va_value[$va_path_components['field_name']] = $this->getMediaUrl($va_path_components['table_name'] . '.' . $va_path_components['field_name'], $vs_version, $pa_options); } else { $va_value[$va_path_components['field_name']] = $this->getMediaTag($va_path_components['table_name'] . '.' . $va_path_components['field_name'], $vs_version, $pa_options); } } break; default: // noop break; } $vs_prop = $va_value[$va_path_components['field_name']]; // Decode list items to text if (isset($pa_options['convertCodesToDisplayText']) && $pa_options['convertCodesToDisplayText'] && ($vs_list_code = $t_instance->getFieldInfo($va_path_components['field_name'], "LIST_CODE"))) { $va_value[$va_path_components['field_name']] = $t_list->getItemFromListForDisplayByItemID($vs_list_code, $vs_prop); } else { if (isset($pa_options['convertCodesToDisplayText']) && $pa_options['convertCodesToDisplayText'] && ($vs_list_code = $t_instance->getFieldInfo($va_path_components['field_name'], "LIST"))) { $va_value[$va_path_components['field_name']] = $t_list->getItemFromListForDisplayByItemValue($vs_list_code, $vs_prop); } else { if (isset($pa_options['convertCodesToDisplayText']) && $pa_options['convertCodesToDisplayText'] && $va_path_components['field_name'] === 'locale_id' && (int) $vs_prop > 0) { $t_locale = new ca_locales($vs_prop); $va_value[$va_path_components['field_name']] = $t_locale->getName(); } else { if (isset($pa_options['convertCodesToDisplayText']) && $pa_options['convertCodesToDisplayText'] && is_array($va_list = $t_instance->getFieldInfo($va_path_components['field_name'], "BOUNDS_CHOICE_LIST"))) { foreach ($va_list as $vs_option => $vs_value) { if ($vs_value == $vs_prop) { $va_value[$va_path_components['field_name']] = $vs_option; break; } } } } } } $vs_pk = $this->opo_datamodel->getTablePrimaryKeyName($va_original_path_components['table_name']); if ($vs_template) { foreach ($va_value_list as $vn_id => $va_values) { foreach ($va_values as $vn_i => $va_value) { $vs_prop = caProcessTemplateForIDs($vs_template, $va_original_path_components['table_name'], array($va_value[$vs_pk]), array('returnAsArray' => false)); $va_return_values[] = $vs_prop; $va_ids[] = $va_value[$vs_pk]; } } } else { $vs_prop = $va_value[$va_path_components['field_name']]; $va_return_values[] = $vs_prop; if ($vb_is_related) { $va_ids[] = $va_value[$vs_pk]; } } } } if ($vb_return_as_link && $vb_is_related) { $va_return_values = caCreateLinksFromText($va_return_values, $va_original_path_components['table_name'], $va_ids, $vs_return_as_link_class, $vs_return_as_link_target); } if (isset($pa_options['convertLineBreaks']) && $pa_options['convertLineBreaks']) { return caConvertLineBreaks(join($vs_delimiter, $va_return_values)); } else { return join($vs_delimiter, $va_return_values); } } } return null; }