/**
  * Returns all available bundle display placements - those data bundles that can be displayed for the given content type, in other words.
  * The returned value is a list of arrays; each array contains a 'bundle' specifier than can be passed got Model::get() or SearchResult::get() and a display name
  *
  * @param mixed $pm_table_name_or_num The table name or number specifying the content type to fetch bundles for. If omitted the content table of the currently loaded display will be used.
  * @param array $pa_options Support options are
  *		no_cache = if set caching of underlying data required to generate list is disabled. This is required in certain situations such as during installation. Only set this if you suspect stale data is being used to generate the list. Eg. if you've been changing metadata attributes in the same request in which you call this method. Default is false.
  *		no_tooltips = if set no tooltips for available bundles will be emitted. Default is false - tooltips will be emitted.
  *		format = specifies label format for bundles. Valid values are "simple" (just the name of the element) or "full" (name of element, name of type of item element pertains to and alternate label, if defined). Default is "full"
  * @return array And array of bundles keyed on display label. Each value is an array with these keys:
  *		bundle = The bundle name (eg. ca_objects.idno)
  *		display = Display label for each available bundle
  *		description = Description of bundle
  * 
  * Will return null if table name or number is invalid.
  */
 public function getAvailableBundles($pm_table_name_or_num = null, $pa_options = null)
 {
     if (!$pm_table_name_or_num) {
         $pm_table_name_or_num = $this->get('table_num');
     }
     $pm_table_name_or_num = $this->getAppDatamodel()->getTableNum($pm_table_name_or_num);
     if (!$pm_table_name_or_num) {
         return null;
     }
     $vb_show_tooltips = isset($pa_options['no_tooltips']) && (bool) $pa_options['no_tooltips'] ? false : true;
     $vs_format = isset($pa_options['format']) && in_array($pa_options['format'], array('simple', 'full')) ? $pa_options['format'] : 'full';
     $t_instance = $this->getAppDatamodel()->getInstanceByTableNum($pm_table_name_or_num, false);
     $vs_table = $t_instance->tableName();
     $vs_table_display_name = $t_instance->getProperty('NAME_PLURAL');
     $va_available_bundles = array();
     $t_placement = new ca_bundle_display_placements(null, array());
     if ($this->inTransaction()) {
         $t_placement->setTransaction($this->getTransaction());
     }
     // get intrinsic fields
     $va_additional_settings = array('maximum_length' => array('formatType' => FT_NUMBER, 'displayType' => DT_FIELD, 'width' => 6, 'height' => 1, 'takesLocale' => false, 'default' => 100, 'label' => _t('Maximum length'), 'description' => _t('Maximum length, in characters, of displayed information.')));
     foreach ($t_instance->getFormFields() as $vs_f => $va_info) {
         if (isset($va_info['DONT_USE_AS_BUNDLE']) && $va_info['DONT_USE_AS_BUNDLE']) {
             continue;
         }
         if ($t_instance->getFieldInfo($vs_f, 'ALLOW_BUNDLE_ACCESS_CHECK')) {
             if (caGetBundleAccessLevel($vs_table, $vs_f) == __CA_BUNDLE_ACCESS_NONE__) {
                 continue;
             }
         }
         $vs_bundle = $vs_table . '.' . $vs_f;
         $vs_display = "<div id='bundleDisplayEditorBundle_{$vs_table}_{$vs_f}'><span class='bundleDisplayEditorPlacementListItemTitle'>" . caUcFirstUTF8Safe($t_instance->getProperty('NAME_SINGULAR')) . "</span> " . ($vs_label = $t_instance->getDisplayLabel($vs_bundle)) . "</div>";
         $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'display' => $vs_format == 'simple' ? $vs_label : $vs_display, 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle), 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => $va_additional_settings);
         if ($vb_show_tooltips) {
             TooltipManager::add("#bundleDisplayEditorBundle_{$vs_table}_{$vs_f}", $this->_formatBundleTooltip($vs_label, $vs_bundle, $vs_description));
         }
     }
     // get attributes
     $va_element_codes = $t_instance->getApplicableElementCodes(null, false, $pa_options['no_cache']);
     $t_md = new ca_metadata_elements();
     if ($this->inTransaction()) {
         $t_md->setTransaction($this->getTransaction());
     }
     $va_all_elements = $t_md->getElementsAsList();
     $va_additional_settings = array('format' => array('formatType' => FT_TEXT, 'displayType' => DT_FIELD, 'width' => 35, 'height' => 5, 'takesLocale' => false, 'default' => '', 'label' => _t('Display format'), 'description' => _t('Template used to format output.'), 'helpText' => ''), 'delimiter' => array('formatType' => FT_TEXT, 'displayType' => DT_FIELD, 'width' => 35, 'height' => 1, 'takesLocale' => false, 'default' => '', 'label' => _t('Delimiter'), 'description' => _t('Text to place in-between repeating values.')), 'maximum_length' => array('formatType' => FT_NUMBER, 'displayType' => DT_FIELD, 'width' => 6, 'height' => 1, 'takesLocale' => false, 'default' => 2048, 'label' => _t('Maximum length'), 'description' => _t('Maximum length, in characters, of displayed information.')), 'filter' => array('formatType' => FT_TEXT, 'displayType' => DT_FIELD, 'width' => 35, 'height' => 5, 'takesLocale' => false, 'default' => '', 'label' => _t('Filter using expression'), 'description' => _t('Expression to filter values with. Leave blank if you do not wish to filter values.')));
     foreach ($va_element_codes as $vn_element_id => $vs_element_code) {
         if (!is_null($va_all_elements[$vn_element_id]['settings']['canBeUsedInDisplay']) && !$va_all_elements[$vn_element_id]['settings']['canBeUsedInDisplay']) {
             continue;
         }
         $t_placement = new ca_bundle_display_placements(null, $va_additional_settings);
         if ($this->inTransaction()) {
             $t_placement->setTransaction($this->getTransaction());
         }
         if (caGetBundleAccessLevel($vs_table, $vs_element_code) == __CA_BUNDLE_ACCESS_NONE__) {
             continue;
         }
         switch ($va_all_elements[$vn_element_id]['datatype']) {
             case 3:
                 // list
                 $va_even_more_settings = array('sense' => array('formatType' => FT_TEXT, 'displayType' => DT_SELECT, 'width' => 20, 'height' => 1, 'takesLocale' => false, 'default' => 'singular', 'options' => array(_t('Singular') => 'singular', _t('Plural') => 'plural'), 'label' => _t('Sense'), 'description' => _t('Determines if value used is singular or plural version.')));
                 break;
             case 0:
                 // container (allows sub-elements to be summarized)
             // container (allows sub-elements to be summarized)
             case 6:
                 // Currency
             // Currency
             case 8:
                 // Length
             // Length
             case 9:
                 // Weight
             // Weight
             case 10:
                 // Timecode
             // Timecode
             case 11:
                 // Integer
             // Integer
             case 12:
                 // Numeric (decimal)
                 $va_even_more_settings = array('bottom_line' => array('formatType' => FT_TEXT, 'displayType' => DT_FIELD, 'width' => 35, 'height' => 5, 'takesLocale' => false, 'default' => '', 'label' => _t('Bottom line format'), 'description' => _t('Template to format aggregate data for display under this column. The template can include these aggregate data tags: ^PAGEAVG, ^AVG, ^PAGESUM, ^SUM, ^PAGEMin, ^MIN, ^PAGEMAX, ^MAX. For containers follow the tag with the element code of the subelement to aggregate. Ex. ^SUM:dimensions_width')));
                 if ($va_all_elements[$vn_element_id]['datatype'] == 6) {
                     $va_even_more_settings['display_currency_conversion'] = array('formatType' => FT_NUMBER, 'displayType' => DT_CHECKBOXES, 'width' => 10, 'height' => 1, 'takesLocale' => false, 'default' => '0', 'label' => _t('Display currency conversion?'), 'description' => _t('Check this option if you want your currency values to be displayed in both the specified and local currency.'));
                 }
                 break;
             default:
                 $va_even_more_settings = array();
                 break;
         }
         $vs_bundle = $vs_table . '.' . $vs_element_code;
         $va_even_more_settings['format'] = $va_additional_settings['format'];
         //$va_even_more_settings['format']['helpText'] = $this->getTemplatePlaceholderDisplayListForBundle($vs_bundle);
         $t_placement = new ca_bundle_display_placements(null, array_merge($va_additional_settings, $va_even_more_settings));
         if ($this->inTransaction()) {
             $t_placement->setTransaction($this->getTransaction());
         }
         $vs_display = "<div id='bundleDisplayEditorBundle_{$vs_table}_{$vs_element_code}'><span class='bundleDisplayEditorPlacementListItemTitle'>" . caUcFirstUTF8Safe($t_instance->getProperty('NAME_SINGULAR')) . "</span> " . ($vs_label = $t_instance->getDisplayLabel($vs_bundle)) . "</div>";
         $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'display' => $vs_format == 'simple' ? $vs_label : $vs_display, 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle), 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => array_merge($va_additional_settings, $va_even_more_settings));
         if ($vb_show_tooltips) {
             TooltipManager::add("#bundleDisplayEditorBundle_{$vs_table}_{$vs_element_code}", $this->_formatBundleTooltip($vs_label, $vs_bundle, $vs_description));
         }
     }
     if (caGetBundleAccessLevel($vs_table, "preferred_labels") != __CA_BUNDLE_ACCESS_NONE__) {
         // get preferred labels for this table
         $va_additional_settings = array('format' => array('formatType' => FT_TEXT, 'displayType' => DT_FIELD, 'width' => 35, 'height' => 5, 'takesLocale' => false, 'default' => '', 'label' => _t('Display format'), 'description' => _t('Template used to format output.')), 'delimiter' => array('formatType' => FT_TEXT, 'displayType' => DT_FIELD, 'width' => 35, 'height' => 1, 'takesLocale' => false, 'default' => '', 'label' => _t('Delimiter'), 'description' => _t('Text to place in-between repeating values.')), 'maximum_length' => array('formatType' => FT_NUMBER, 'displayType' => DT_FIELD, 'width' => 6, 'height' => 1, 'takesLocale' => false, 'default' => 100, 'label' => _t('Maximum length'), 'description' => _t('Maximum length, in characters, of displayed information.')));
         $t_placement = new ca_bundle_display_placements(null, $va_additional_settings);
         if ($this->inTransaction()) {
             $t_placement->setTransaction($this->getTransaction());
         }
         $vs_bundle = $vs_table . '.preferred_labels';
         $vs_display = "<div id='bundleDisplayEditorBundle_{$vs_table}_preferred_labels'><span class='bundleDisplayEditorPlacementListItemTitle'>" . caUcFirstUTF8Safe($t_instance->getProperty('NAME_SINGULAR')) . "</span> " . ($vs_label = $t_instance->getDisplayLabel($vs_bundle)) . "</div>";
         $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'display' => $vs_format == 'simple' ? $vs_label : $vs_display, 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle), 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => $va_additional_settings);
         if ($vb_show_tooltips) {
             TooltipManager::add("#bundleDisplayEditorBundle_{$vs_table}_preferred_labels", $this->_formatBundleTooltip($vs_label, $vs_bundle, $vs_description));
         }
     }
     if (caGetBundleAccessLevel($vs_table, "nonpreferred_labels") != __CA_BUNDLE_ACCESS_NONE__) {
         // get non-preferred labels for this table
         $t_placement = new ca_bundle_display_placements(null, $va_additional_settings);
         if ($this->inTransaction()) {
             $t_placement->setTransaction($this->getTransaction());
         }
         $vs_bundle = $vs_table . '.nonpreferred_labels';
         $vs_display = "<div id='bundleDisplayEditorBundle_{$vs_table}_nonpreferred_labels'><span class='bundleDisplayEditorPlacementListItemTitle'>" . caUcFirstUTF8Safe($t_instance->getProperty('NAME_SINGULAR')) . "</span> " . ($vs_label = $t_instance->getDisplayLabel($vs_bundle)) . "</div>";
         $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'display' => $vs_format == 'simple' ? $vs_label : $vs_display, 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle), 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => $va_additional_settings);
         if ($vb_show_tooltips) {
             TooltipManager::add("#bundleDisplayEditorBundle_{$vs_table}_nonpreferred_labels", $this->_formatBundleTooltip($vs_label, $vs_bundle, $vs_description));
         }
     }
     // get library checkout and commerce order history bundle (objects only, of course)
     if ($vs_table == 'ca_objects') {
         $va_additional_settings = array('order_type' => array('formatType' => FT_TEXT, 'displayType' => DT_SELECT, 'width' => 35, 'height' => 1, 'takesLocale' => false, 'default' => '', 'options' => array(_t('Sales order') => 'O', _t('Loan') => 'L'), 'label' => _t('Type of order'), 'description' => _t('Determines which type of order is displayed.')));
         $t_placement = new ca_bundle_display_placements(null, $va_additional_settings);
         if ($this->inTransaction()) {
             $t_placement->setTransaction($this->getTransaction());
         }
         $vs_bundle = 'ca_commerce_order_history';
         $vs_label = _t('Order history');
         $vs_display = _t('Order history');
         $vs_description = _t('List of orders (loans or sales) that include this object');
         $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'display' => $vs_format == 'simple' ? $vs_label : $vs_display, 'description' => $vs_description, 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => $va_additional_settings);
         if ($vb_show_tooltips) {
             TooltipManager::add("#bundleDisplayEditorBundle_ca_commerce_order_history", $this->_formatBundleTooltip($vs_label, $vs_bundle, $vs_description));
         }
         $va_additional_settings = array('format' => array('formatType' => FT_TEXT, 'displayType' => DT_FIELD, 'width' => 35, 'height' => 5, 'takesLocale' => false, 'default' => '', 'label' => _t('Display format'), 'description' => _t('Template used to format output.')));
         $t_placement = new ca_bundle_display_placements(null, $va_additional_settings);
         if ($this->inTransaction()) {
             $t_placement->setTransaction($this->getTransaction());
         }
         $vs_bundle = 'ca_object_checkouts';
         $vs_label = _t('Library checkouts');
         $vs_display = "<div id='bundleDisplayEditorBundle_{$vs_table}_preferred_labels'><span class='bundleDisplayEditorPlacementListItemTitle'>" . caUcFirstUTF8Safe($t_instance->getProperty('NAME_SINGULAR')) . "</span> " . _t('Library checkouts') . "</div>";
         $vs_description = _t('List of library checkouts that include this object');
         $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'display' => $vs_format == 'simple' ? $vs_label : $vs_display, 'description' => $vs_description, 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => $va_additional_settings);
         if ($vb_show_tooltips) {
             TooltipManager::add("#bundleDisplayEditorBundle_ca_object_checkouts", $this->_formatBundleTooltip($vs_label, $vs_bundle, $vs_description));
         }
         $va_additional_settings = array();
         $t_placement = new ca_bundle_display_placements(null, $va_additional_settings);
         if ($this->inTransaction()) {
             $t_placement->setTransaction($this->getTransaction());
         }
         $vs_bundle = $vs_table . '.ca_objects_location';
         $vs_label = _t('Current location');
         $vs_display = "<div id='bundleDisplayEditorBundle_{$vs_table}_ca_objects_location'><span class='bundleDisplayEditorPlacementListItemTitle'>" . caUcFirstUTF8Safe($t_instance->getProperty('NAME_SINGULAR')) . "</span> " . _t('Current location') . "</div>";
         $vs_description = _t('Current location of object');
         $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'display' => $vs_format == 'simple' ? $vs_label : $vs_display, 'description' => $vs_description, 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => $va_additional_settings);
         if ($vb_show_tooltips) {
             TooltipManager::add("#bundleDisplayEditorBundle_ca_objects_location", $this->_formatBundleTooltip($vs_label, $vs_bundle, $vs_description));
         }
     }
     if (caGetBundleAccessLevel($vs_table, "ca_object_representations") != __CA_BUNDLE_ACCESS_NONE__) {
         // get object representations (objects only, of course)
         if ($vs_table == 'ca_objects') {
             $va_additional_settings = array('display_mode' => array('formatType' => FT_TEXT, 'displayType' => DT_SELECT, 'width' => 35, 'height' => 1, 'takesLocale' => false, 'default' => '', 'options' => array(_t('Media') => 'media', _t('URL') => 'url'), 'label' => _t('Output mode'), 'description' => _t('Determines if value used is URL of media or the media itself.')));
             $o_media_settings = new MediaProcessingSettings('ca_object_representations', 'media');
             $va_versions = $o_media_settings->getMediaTypeVersions('*');
             foreach ($va_versions as $vs_version => $va_version_info) {
                 $t_placement = new ca_bundle_display_placements(null, $va_additional_settings);
                 if ($this->inTransaction()) {
                     $t_placement->setTransaction($this->getTransaction());
                 }
                 $vs_bundle = 'ca_object_representations.media.' . $vs_version;
                 $vs_display = "<div id='bundleDisplayEditorBundle_ca_object_representations_media_{$vs_version}'><span class='bundleDisplayEditorPlacementListItemTitle'>" . caUcFirstUTF8Safe($t_instance->getProperty('NAME_SINGULAR')) . "</span> " . ($vs_label = $t_instance->getDisplayLabel($vs_bundle)) . "</div>";
                 $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'display' => $vs_format == 'simple' ? $vs_label : $vs_display, 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle), 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => $va_additional_settings);
                 if ($vb_show_tooltips) {
                     TooltipManager::add("#bundleDisplayEditorBundle_ca_object_representations_media_{$vs_version}", $this->_formatBundleTooltip($vs_label, $vs_bundle, $vs_description));
                 }
             }
             $t_rep = new ca_object_representations();
             if ($this->inTransaction()) {
                 $t_rep->setTransaction($this->getTransaction());
             }
             foreach (array('mimetype', 'md5', 'original_filename') as $vs_rep_field) {
                 $vs_bundle = 'ca_object_representations.' . $vs_rep_field;
                 $vs_display = "<div id='bundleDisplayEditorBundle_ca_object_representations_{$vs_rep_field}'><span class='bundleDisplayEditorPlacementListItemTitle'>" . caUcFirstUTF8Safe($t_rep->getProperty('NAME_SINGULAR')) . "</span> " . ($vs_label = $t_rep->getDisplayLabel($vs_bundle)) . "</div>";
                 $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'display' => $vs_format == 'simple' ? $vs_label : $vs_display, 'description' => $vs_description = $t_rep->getDisplayDescription($vs_bundle), 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => array());
             }
         }
     }
     // get related items
     $o_dm = $this->getAppDatamodel();
     foreach (array('ca_objects', 'ca_object_lots', 'ca_entities', 'ca_places', 'ca_occurrences', 'ca_collections', 'ca_storage_locations', 'ca_loans', 'ca_movements', 'ca_list_items', 'ca_object_representations') as $vs_related_table) {
         if ($this->getAppConfig()->get($vs_related_table . '_disable') && !($vs_related_table == 'ca_object_representations' && !$this->getAppConfig()->get('ca_objects_disable'))) {
             continue;
         }
         if (caGetBundleAccessLevel($vs_table, $vs_related_table) == __CA_BUNDLE_ACCESS_NONE__) {
             continue;
         }
         if ($vs_related_table === $vs_table) {
             $vs_bundle = $vs_related_table . '.related';
         } else {
             $vs_bundle = $vs_related_table;
         }
         $t_rel_instance = $o_dm->getInstanceByTableName($vs_related_table, true);
         $vs_table_name = $o_dm->getTableName($this->get('table_num'));
         $va_path = array_keys($o_dm->getPath($vs_table_name, $vs_related_table));
         if (sizeof($va_path) < 2 || sizeof($va_path) > 3) {
             continue;
         }
         // only use direct relationships (one-many or many-many)
         $va_additional_settings = array('format' => array('formatType' => FT_TEXT, 'displayType' => DT_FIELD, 'width' => 35, 'height' => 5, 'takesLocale' => false, 'default' => '', 'label' => _t('Display format'), 'description' => _t('Template used to format output.')), 'restrict_to_relationship_types' => array('formatType' => FT_TEXT, 'displayType' => DT_SELECT, 'useRelationshipTypeList' => $va_path[1], 'width' => 35, 'height' => 5, 'takesLocale' => false, 'default' => '', 'label' => _t('Restrict to relationship types'), 'description' => _t('Restricts display to items related using the specified relationship type(s). Leave all unchecked for no restriction.')), 'restrict_to_types' => array('formatType' => FT_TEXT, 'displayType' => DT_SELECT, 'useList' => $t_rel_instance->getTypeListCode(), 'width' => 35, 'height' => 5, 'takesLocale' => false, 'default' => '', 'label' => _t('Restrict to types'), 'description' => _t('Restricts display to items of the specified type(s). Leave all unchecked for no restriction.')), 'delimiter' => array('formatType' => FT_TEXT, 'displayType' => DT_FIELD, 'width' => 35, 'height' => 1, 'takesLocale' => false, 'default' => '', 'label' => _t('Delimiter'), 'description' => _t('Text to place in-between repeating values.')));
         if ($t_rel_instance->isHierarchical()) {
             $va_additional_settings += array('show_hierarchy' => array('formatType' => FT_NUMBER, 'displayType' => DT_CHECKBOXES, 'width' => 10, 'height' => 1, 'hideOnSelect' => array('format'), 'takesLocale' => false, 'default' => '0', 'label' => _t('Show hierarchy?'), 'description' => _t('If checked the full hierarchical path will be shown.')), 'remove_first_items' => array('formatType' => FT_NUMBER, 'displayType' => DT_FIELD, 'width' => 10, 'height' => 1, 'takesLocale' => false, 'default' => '0', 'label' => _t('Remove first items from hierarchy?'), 'description' => _t('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.')), 'hierarchy_order' => array('formatType' => FT_TEXT, 'displayType' => DT_SELECT, 'options' => array(_t('top first') => 'ASC', _t('bottom first') => 'DESC'), 'width' => 35, 'height' => 1, 'takesLocale' => false, 'default' => '', 'label' => _t('Order hierarchy'), 'description' => _t('Determines order in which hierarchy is displayed.')), 'hierarchy_limit' => array('formatType' => FT_NUMBER, 'displayType' => DT_FIELD, 'width' => 10, 'height' => 1, 'takesLocale' => false, 'default' => '', 'label' => _t('Maximum length of hierarchy'), 'description' => _t('Maximum number of items to show in the hierarchy. Leave blank to show the unabridged hierarchy.')), 'hierarchical_delimiter' => array('formatType' => FT_TEXT, 'displayType' => DT_FIELD, 'width' => 35, 'height' => 1, 'takesLocale' => false, 'default' => ' ➔ ', 'label' => _t('Hierarchical delimiter'), 'description' => _t('Text to place in-between elements of a hierarchical value.')));
         }
         if ($vs_table === 'ca_objects' && $vs_related_table === 'ca_storage_locations' || $vs_table === 'ca_storage_locations' && $vs_related_table === 'ca_objects' || $vs_table === 'ca_objects' && $vs_related_table === 'ca_movements' || $vs_table === 'ca_movements' && $vs_related_table === 'ca_objects' || $vs_table === 'ca_storage_locations' && $vs_related_table === 'ca_movements' || $vs_table === 'ca_movements' && $vs_related_table === 'ca_storage_locations') {
             $va_additional_settings['showCurrentOnly'] = array('formatType' => FT_TEXT, 'displayType' => DT_CHECKBOXES, 'width' => "10", 'height' => "1", 'takesLocale' => false, 'default' => '0', 'label' => _t('Show current only?'), 'description' => _t('If checked only current objects are displayed.'));
         }
         //$va_additional_settings['format']['helpText'] = $this->getTemplatePlaceholderDisplayListForBundle($vs_bundle);
         $t_placement = new ca_bundle_display_placements(null, $va_additional_settings);
         if ($this->inTransaction()) {
             $t_placement->setTransaction($this->getTransaction());
         }
         $vs_id_suffix = "bundleDisplayEditorBundle_" . str_replace(".", "_", $vs_bundle);
         $vs_display = "<div id='bundleDisplayEditorBundle_{$vs_id_suffix}'><span class='bundleDisplayEditorPlacementListItemTitle'>" . caUcFirstUTF8Safe($t_rel_instance->getProperty('NAME_SINGULAR')) . "</span> " . ($vs_label = $t_rel_instance->getDisplayLabel($vs_bundle)) . "</div>";
         $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'display' => $vs_format == 'simple' ? $vs_label : $vs_display, 'description' => $vs_description = $t_rel_instance->getDisplayDescription($vs_bundle), 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => $va_additional_settings);
         if ($vb_show_tooltips) {
             TooltipManager::add("#bundleDisplayEditorBundle_{$vs_id_suffix}", $this->_formatBundleTooltip($vs_label, $vs_bundle, $vs_description));
         }
     }
     // created and modified
     $va_additional_settings = array('dateFormat' => array('formatType' => FT_TEXT, 'displayType' => DT_SELECT, 'width' => 40, 'height' => 1, 'takesLocale' => false, 'default' => 'iso8601', 'options' => array('ISO-8601' => 'iso8601', 'Text' => 'text'), 'label' => _t('Date format'), 'description' => _t('Sets format for output of date when exporting.')));
     $t_placement = new ca_bundle_display_placements(null, $va_additional_settings);
     if ($this->inTransaction()) {
         $t_placement->setTransaction($this->getTransaction());
     }
     $vs_bundle = "{$vs_table}.created";
     $vs_display = "<div id='bundleDisplayEditorBundle_{$vs_table}_created'><span class='bundleDisplayEditorPlacementListItemTitle'>" . _t('General') . "</span> " . ($vs_label = $t_instance->getDisplayLabel($vs_bundle)) . "</div>";
     $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'display' => $vs_format == 'simple' ? $vs_label : $vs_display, 'description' => $vs_description = _t('Date and time item was created'), 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => $va_additional_settings);
     if ($vb_show_tooltips) {
         TooltipManager::add("#bundleDisplayEditorBundle_{$vs_table}_created", $this->_formatBundleTooltip($vs_label, $vs_bundle, $vs_description));
     }
     $vs_bundle = "{$vs_table}.lastModified";
     $vs_display = "<div id='bundleDisplayEditorBundle_{$vs_table}_lastModified'><span class='bundleDisplayEditorPlacementListItemTitle'>" . _t('General') . "</span> " . ($vs_label = $t_instance->getDisplayLabel($vs_bundle)) . "</div>";
     $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'display' => $vs_display, 'description' => $vs_description = _t('Date and time item was last modified'), 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => $va_additional_settings);
     if ($vb_show_tooltips) {
         TooltipManager::add("#bundleDisplayEditorBundle_{$vs_table}_lastModified", $this->_formatBundleTooltip($vs_label, $vs_bundle, $vs_description));
     }
     ksort($va_available_bundles);
     $va_sorted_bundles = array();
     foreach ($va_available_bundles as $vs_k => $va_val) {
         foreach ($va_val as $vs_real_key => $va_info) {
             $va_sorted_bundles[$vs_real_key] = $va_info;
         }
     }
     return $va_sorted_bundles;
 }
 /** 
  * Returns labels associated with this row. By default all labels - preferred and non-preferred, and from all locales -
  * are returned. You can limit the returned labels to specified locales by passing a list of locale_ids (numeric ids, *not* locale codes)
  * in $pn_locale_ids. Similarly you can limit return labels to preferred on non-preferred by setting $pn_mode to __CA_LABEL_TYPE_PREFERRED__
  * or __CA_LABEL_TYPE_NONPREFERRED__
  *
  * getLabels() returns an associated array keyed by the primary key of the item the label is attached to; each value is an array keyed by locale_id, the values of which
  * is a list of associative arrays with the label table data. This return format is designed to be digested by the displayHelper function caExtractValuesByUserLocale()
  *
  * @param array $pa_locale_ids
  * @param int $pn_mode
  * @param boolean $pb_dont_cache
  * @param array $pa_options Array of options. Supported options are:
  *			row_id = The row_id to return labels for. If omitted the id of the currently loaded row is used. If row_id is not set and now row is loaded then getLabels() will return null.
  *			restrict_to_types = an optional array of numeric type ids or alphanumeric type identifiers to restrict the returned labels to. The types are list items in a list specified in app.conf (or, if not defined there, by hardcoded constants in the model)
  *			restrictToTypes = synonym for restrict_to_types
  *			extractValuesByUserLocale = if set returned array of values is filtered to include only values appropriate for the current user's locale
  *			forDisplay = if true, a simple list of labels ready for display is returned; implies the extractValuesByUserLocale option
  *
  * @return array List of labels
  */
 public function getLabels($pa_locale_ids = null, $pn_mode = __CA_LABEL_TYPE_ANY__, $pb_dont_cache = true, $pa_options = null)
 {
     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 (!($vn_id = $this->getPrimaryKey()) && !(isset($pa_options['row_id']) && ($vn_id = $pa_options['row_id']))) {
         return null;
     }
     if (isset($pa_options['forDisplay']) && $pa_options['forDisplay']) {
         $pa_options['extractValuesByUserLocale'] = true;
     }
     if ($pn_mode == __CA_LABEL_TYPE_ANY__ && caGetBundleAccessLevel($this->tableName(), 'preferred_labels') == __CA_BUNDLE_ACCESS_NONE__) {
         $pn_mode = __CA_LABEL_TYPE_NONPREFERRED__;
     }
     if ($pn_mode == __CA_LABEL_TYPE_ANY__ && caGetBundleAccessLevel($this->tableName(), 'nonpreferred_labels') == __CA_BUNDLE_ACCESS_NONE__) {
         $pn_mode = __CA_LABEL_TYPE_PREFERRED__;
     }
     if ($pn_mode == __CA_LABEL_TYPE_PREFERRED__ && caGetBundleAccessLevel($this->tableName(), 'preferred_labels') == __CA_BUNDLE_ACCESS_NONE__) {
         return null;
     }
     if ($pn_mode == __CA_LABEL_TYPE_NONPREFERRED__ && caGetBundleAccessLevel($this->tableName(), 'nonpreferred_labels') == __CA_BUNDLE_ACCESS_NONE__) {
         return null;
     }
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     $vs_cache_key = caMakeCacheKeyFromOptions(array_merge($pa_options, array('table_name' => $this->tableName(), 'id' => $vn_id, 'mode' => (int) $pn_mode)));
     if (!$pb_dont_cache && is_array($va_tmp = LabelableBaseModelWithAttributes::$s_label_cache[$this->tableName()][$vn_id][$vs_cache_key])) {
         return $va_tmp;
     }
     if (!($t_label = $this->_DATAMODEL->getInstanceByTableName($this->getLabelTableName(), true))) {
         return null;
     }
     if ($this->inTransaction()) {
         $o_trans = $this->getTransaction();
         $t_label->setTransaction($o_trans);
     }
     $vs_label_where_sql = 'WHERE (l.' . $this->primaryKey() . ' = ?)';
     $vs_locale_join_sql = '';
     if ($pa_locale_ids) {
         $vs_label_where_sql .= ' AND (l.locale_id IN (' . join(',', $pa_locale_ids) . '))';
     }
     $vs_locale_join_sql = 'INNER JOIN ca_locales AS loc ON loc.locale_id = l.locale_id';
     $vs_list_code = null;
     if ($t_label->hasField('is_preferred')) {
         switch ($pn_mode) {
             case __CA_LABEL_TYPE_PREFERRED__:
                 $vs_list_code = $this->_CONFIG->get($this->tableName() . '_preferred_label_type_list');
                 $vs_label_where_sql .= ' AND (l.is_preferred = 1)';
                 break;
             case __CA_LABEL_TYPE_NONPREFERRED__:
                 $vs_list_code = $this->_CONFIG->get($this->tableName() . '_nonpreferred_label_type_list');
                 $vs_label_where_sql .= ' AND (l.is_preferred = 0)';
                 break;
             default:
                 $vs_list_code = $this->_CONFIG->get($this->tableName() . '_preferred_label_type_list');
                 break;
         }
         if (!$vs_list_code) {
             if ($t_label_instance = $this->getLabelTableInstance()) {
                 $vs_list_code = $t_label_instance->getFieldInfo('type_id', 'LIST_CODE');
             }
         }
     }
     // limit related items to a specific type
     $vs_restrict_to_type_sql = '';
     if (isset($pa_options['restrict_to_type']) && $pa_options['restrict_to_type']) {
         if (!isset($pa_options['restrict_to_types']) || !is_array($pa_options['restrict_to_types'])) {
             $pa_options['restrict_to_types'] = array();
         }
         $pa_options['restrict_to_types'][] = $pa_options['restrict_to_type'];
     }
     if (isset($pa_options['restrict_to_types']) && $pa_options['restrict_to_types'] && is_array($pa_options['restrict_to_types']) && $vs_list_code) {
         $t_list = new ca_lists();
         $t_list_item = new ca_list_items();
         $va_ids = array();
         foreach ($pa_options['restrict_to_types'] as $vs_type) {
             if (!($vn_restrict_to_type_id = (int) $t_list->getItemIDFromList($vs_list_code, $vs_type))) {
                 $vn_restrict_to_type_id = (int) $vs_type;
             }
             if ($vn_restrict_to_type_id) {
                 $va_children = $t_list_item->getHierarchyChildren($vn_restrict_to_type_id, array('idsOnly' => true));
                 $va_ids = array_merge($va_ids, $va_children);
                 $va_ids[] = $vn_restrict_to_type_id;
             }
         }
         if (sizeof($va_ids) > 0) {
             $vs_restrict_to_type_sql = ' AND l.type_id IN (' . join(',', $va_ids) . ')';
         }
     }
     $o_db = $this->getDb();
     $qr_res = $o_db->query("\n \t\t\t\tSELECT l.*, loc.country locale_country, loc.language locale_language, loc.dialect locale_dialect, loc.name locale_name\n \t\t\t\tFROM " . $this->getLabelTableName() . " l\n \t\t\t\t{$vs_locale_join_sql}\n \t\t\t\t{$vs_label_where_sql}\n \t\t\t\t{$vs_restrict_to_type_sql}\n \t\t\t\tORDER BY\n \t\t\t\t\tloc.name\n \t\t\t", (int) $vn_id);
     $va_labels = array();
     $t_label->clear();
     while ($qr_res->nextRow()) {
         $va_labels[$vn_id][$qr_res->get('locale_id')][] = array_merge($qr_res->getRow(), array('form_element' => $t_label->htmlFormElement($this->getLabelDisplayField(), null)));
     }
     if (isset($pa_options['extractValuesByUserLocale']) && $pa_options['extractValuesByUserLocale']) {
         $va_labels = caExtractValuesByUserLocale($va_labels);
     }
     if (isset($pa_options['forDisplay']) && $pa_options['forDisplay']) {
         $vs_display_field = $this->getLabelDisplayField();
         $va_flattened_labels = array();
         foreach ($va_labels as $vn_id => $va_label_list) {
             foreach ($va_label_list as $vn_i => $va_label) {
                 $va_flattened_labels[] = $va_label[$vs_display_field];
             }
         }
         $va_labels = $va_flattened_labels;
     }
     LabelableBaseModelWithAttributes::$s_label_cache[$this->tableName()][$vn_id][$vs_cache_key] = $va_labels;
     return $va_labels;
 }
 /**
  * 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;
 }
Esempio n. 4
0
 /**
  * Returns list of screens for a given UI. 
  *
  * @param RequestHTTP $po_request The current request
  * @param int $pn_type_id Optional type to restrict screens to
  * @param array $pa_options Options include:
  *		showAll = Include screens that do not have placements. Default is false.
  *
  * @return array List of screens for this user interface
  */
 public function getScreens($po_request = null, $pn_type_id = null, $pa_options = null)
 {
     if (!$this->getPrimaryKey()) {
         return false;
     }
     $vs_opts_md5 = caMakeCacheKeyFromOptions($pa_options);
     if (!($t_instance = $this->_DATAMODEL->getInstanceByTableNum($this->get('editor_type')))) {
         return null;
     }
     if ($t_instance instanceof BaseRelationshipModel) {
         $va_types = $t_instance->getRelationshipTypes();
     } else {
         $va_types = $t_instance->getTypeList();
     }
     $o_db = $this->getDb();
     $va_type_list = caMakeTypeIDList($this->get('editor_type'), array($pn_type_id), array('dontIncludeSubtypesInTypeRestriction' => true));
     if (!sizeof($va_type_list)) {
         $va_type_list = array($pn_type_id);
     }
     $vs_type_sql = (int) $pn_type_id ? "AND (ceustr.type_id IS NULL OR ceustr.type_id IN (" . join(",", $va_type_list) . "))" : '';
     $qr_res = $o_db->query("\n\t\t\tSELECT ceus.*, ceusl.*, ceustr.type_id restriction_type_id\n\t\t\tFROM ca_editor_ui_screens ceus\n\t\t\tINNER JOIN ca_editor_ui_screen_labels AS ceusl ON ceus.screen_id = ceusl.screen_id\n\t\t\tLEFT JOIN ca_editor_ui_screen_type_restrictions AS ceustr ON ceus.screen_id = ceustr.screen_id\n\t\t\tWHERE\n\t\t\t\t(ceus.ui_id = ?) {$vs_type_sql}\n\t\t\tORDER BY \n\t\t\t\tceus.rank, ceus.screen_id\n\t\t", (int) $this->getPrimaryKey());
     $va_screens = array();
     while ($qr_res->nextRow()) {
         if (!$va_screens[$vn_screen_id = $qr_res->get('screen_id')][$vn_screen_locale_id = $qr_res->get('locale_id')]) {
             $va_screens[$vn_screen_id][$vn_screen_locale_id] = $qr_res->getRow();
             if ((bool) $va_screens[$vn_screen_id][$vn_screen_locale_id]['is_default']) {
                 $va_screens[$vn_screen_id][$vn_screen_locale_id]['isDefault'] = "◉";
             }
             $va_screens[$vn_screen_id][$vn_screen_locale_id]['numPlacements'] = sizeof($this->getScreenBundlePlacements($vn_screen_id));
         }
         if ($qr_res->get('restriction_type_id')) {
             $vs_key_to_add = $t_instance instanceof BaseRelationshipModel ? 'type_code' : 'name_plural';
             $va_screens[$vn_screen_id][$vn_screen_locale_id]['typeRestrictions'][$qr_res->get('restriction_type_id')] = $va_types[$qr_res->get('restriction_type_id')][$vs_key_to_add];
         }
     }
     $va_screens_with_bundles = null;
     if ((!isset($pa_options['showAll']) || !$pa_options['showAll']) && sizeof($va_screens)) {
         // Get placements for all screens, so we can filter screens without placements
         $qr_res = $o_db->query("\n\t\t\t\tSELECT screen_id, placement_id, bundle_name\n\t\t\t\tFROM ca_editor_ui_bundle_placements\n\t\t\t\tWHERE\n\t\t\t\t\tscreen_id IN (?)\n\t\t\t", array(array_keys($va_screens)));
         $vs_table = $t_instance->tableName();
         $va_screens_with_bundles = array();
         while ($qr_res->nextRow()) {
             $vn_screen_id = $qr_res->get('screen_id');
             if (isset($va_screens_with_bundles[$vn_screen_id])) {
                 continue;
             }
             if (caGetBundleAccessLevel($vs_table, $qr_res->get('bundle_name')) != __CA_BUNDLE_ACCESS_NONE__) {
                 $va_screens_with_bundles[$vn_screen_id] = true;
             }
         }
     }
     foreach ($va_screens as $vn_screen_id => $va_screen_labels_by_locale) {
         if (is_array($va_screens_with_bundles) && !isset($va_screens_with_bundles[$vn_screen_id])) {
             unset($va_screens[$vn_screen_id]);
             continue;
         }
         foreach ($va_screen_labels_by_locale as $vn_locale_id => $va_restriction_info) {
             if (!is_array($va_screens[$vn_screen_id][$vn_locale_id]['typeRestrictions'])) {
                 continue;
             }
             $va_screens[$vn_screen_id][$vn_locale_id]['typeRestrictionsForDisplay'] = join(', ', $va_screens[$vn_screen_id][$vn_locale_id]['typeRestrictions']);
         }
     }
     return caExtractValuesByUserLocale($va_screens);
 }
Esempio n. 5
0
 /**
  * Implementation of core get() logic
  *
  * @param string $ps_field bundle specifier
  * @param null|array $pa_options options array
  * @return array|null|string
  */
 private function _get($ps_field, $pa_options = null)
 {
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     $vb_return_as_array = isset($pa_options['returnAsArray']) ? (bool) $pa_options['returnAsArray'] : false;
     $vb_return_all_locales = isset($pa_options['returnAllLocales']) ? (bool) $pa_options['returnAllLocales'] : false;
     $vb_return_with_structure = isset($pa_options['returnWithStructure']) ? (bool) $pa_options['returnWithStructure'] : false;
     if ($vb_return_with_structure) {
         $pa_options['returnAsArray'] = $vb_return_as_array = true;
     }
     // returnWithStructure implies returnAsArray
     $vs_delimiter = isset($pa_options['delimiter']) ? $pa_options['delimiter'] : ';';
     $vb_unserialize = isset($pa_options['unserialize']) ? (bool) $pa_options['unserialize'] : false;
     $vb_return_url = isset($pa_options['returnURL']) ? (bool) $pa_options['returnURL'] : false;
     $vb_return_path = isset($pa_options['returnPath']) ? (bool) $pa_options['returnPAth'] : false;
     $vb_convert_codes_to_display_text = isset($pa_options['convertCodesToDisplayText']) ? (bool) $pa_options['convertCodesToDisplayText'] : false;
     $vb_convert_codes_to_idno = isset($pa_options['convertCodesToIdno']) ? (bool) $pa_options['convertCodesToIdno'] : false;
     $vb_use_locale_codes = isset($pa_options['useLocaleCodes']) ? (bool) $pa_options['useLocaleCodes'] : false;
     if (!($vs_output = isset($pa_options['output']) ? (string) $pa_options['output'] : null)) {
         if ($vb_convert_codes_to_display_text) {
             $vs_output = "text";
         }
         if (!$vs_output && $vb_convert_codes_to_idno) {
             $vs_output = "idno";
         }
     }
     if (!in_array($vs_output, array('text', 'idno', 'value'))) {
         $vs_output = 'value';
     }
     $pa_options['output'] = $vs_output;
     if (!($vb_return_as_link = isset($pa_options['makeLink']) ? (bool) $pa_options['makeLink'] : false)) {
         $vb_return_as_link = isset($pa_options['returnAsLink']) ? (bool) $pa_options['returnAsLink'] : false;
     }
     $pa_options['makeLink'] = $vb_return_as_link;
     $vn_max_levels_from_top = isset($pa_options['maxLevelsFromTop']) ? (int) $pa_options['maxLevelsFromTop'] : null;
     $vn_max_levels_from_bottom = isset($pa_options['maxLevelsFromBottom']) ? (int) $pa_options['maxLevelsFromBottom'] : null;
     $vn_remove_first_items = isset($pa_options['removeFirstItems']) ? (int) $pa_options['removeFirstItems'] : 0;
     $va_check_access = isset($pa_options['checkAccess']) ? is_array($pa_options['checkAccess']) ? $pa_options['checkAccess'] : array($pa_options['checkAccess']) : null;
     $vs_template = isset($pa_options['template']) ? (string) $pa_options['template'] : null;
     $va_path_components = isset(SearchResult::$s_parsed_field_component_cache[$this->ops_table_name . '/' . $ps_field]) ? SearchResult::$s_parsed_field_component_cache[$this->ops_table_name . '/' . $ps_field] : $this->parseFieldPathComponents($ps_field);
     $va_val_opts = array_merge($pa_options, array('returnAsArray' => $vb_return_as_array, 'returnAllLocales' => $vb_return_all_locales, 'returnWithStructure' => $vb_return_with_structure, 'pathComponents' => $va_path_components, 'delimiter' => $vs_delimiter, 'makeLink' => $vb_return_as_link, 'returnURL' => $vb_return_url, 'returnPath' => $vb_return_path, 'unserialize' => $vb_unserialize, 'convertCodesToDisplayText' => $vb_convert_codes_to_display_text, 'convertCodesToIdno' => $vb_convert_codes_to_idno, 'checkAccess' => $va_check_access, 'template' => $vs_template, 'useLocaleCodes' => $vb_use_locale_codes));
     if ($va_path_components['table_name'] != $this->ops_table_name) {
         $vs_access_chk_key = $va_path_components['table_name'] . ($va_path_components['field_name'] ? '.' . $va_path_components['field_name'] : '');
     } else {
         $vs_access_chk_key = $va_path_components['field_name'];
     }
     if ($va_path_components['field_name'] !== 'access' && caGetBundleAccessLevel($va_path_components['table_name'], $vs_access_chk_key) == __CA_BUNDLE_ACCESS_NONE__) {
         return null;
     }
     if (!(($vs_value = $this->opo_engine_result->get($ps_field, $pa_options)) === false)) {
         if ($vb_return_as_array) {
             if ($vb_return_all_locales) {
                 return array(1 => $vs_value);
             } else {
                 return array($vs_value);
             }
         } else {
             return $vs_value;
         }
     }
     if (!($t_instance = SearchResult::$s_instance_cache[$va_path_components['table_name']])) {
         $t_instance = SearchResult::$s_instance_cache[$va_path_components['table_name']] = $this->opo_datamodel->getInstanceByTableName($va_path_components['table_name'], true);
     }
     if (!$t_instance) {
         return null;
     }
     // Bad table
     $vn_row_id = $this->opo_engine_result->get($this->ops_table_pk);
     $va_val_opts['primaryKey'] = $t_instance->primaryKey();
     if ($va_path_components['hierarchical_modifier']) {
         if (in_array($va_path_components['field_name'], array('preferred_labels', 'nonpreferred_labels')) && !$va_path_components['subfield_name']) {
             $va_path_components['subfield_name'] = $va_path_components['components'][2] = $t_instance->getLabelDisplayField();
         }
         switch ($va_path_components['hierarchical_modifier']) {
             case 'parent':
                 if ($va_path_components['related']) {
                     // [RELATED TABLE PARENT]
                     if (!isset(SearchResult::$opa_hierarchy_parent_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']])) {
                         $this->prefetchHierarchyParents($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     $va_ids = SearchResult::$opa_hierarchy_parent_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']];
                 } else {
                     // [PRIMARY TABLE PARENT]
                     if (!isset(SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_row_id])) {
                         $this->prefetchHierarchyParents($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     $va_ids = array($vn_row_id);
                 }
                 if (!sizeof($va_ids)) {
                     return $pa_options['returnAsArray'] ? array() : null;
                 }
                 $va_hiers = array();
                 foreach ($va_ids as $vn_id) {
                     $va_parent_ids = array();
                     if (isset(SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_id]) && is_array(SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_id])) {
                         if (!is_array($va_parent_ids = SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_id])) {
                             return $pa_options['returnAsArray'] ? array() : null;
                         }
                     }
                     $va_parent_ids = array_slice($va_parent_ids, 0, 1);
                     if (!($qr_hier = $t_instance->makeSearchResult($va_path_components['table_name'], $va_parent_ids))) {
                         return $pa_options['returnAsArray'] ? array() : null;
                     }
                     $va_tmp = array($va_path_components['table_name']);
                     if ($va_path_components['field_name']) {
                         $va_tmp[] = $va_path_components['field_name'];
                     }
                     if ($va_path_components['subfield_name']) {
                         $va_tmp[] = $va_path_components['subfield_name'];
                     }
                     $vs_hier_fld_name = join(".", $va_tmp);
                     $vs_pk = $t_instance->primaryKey();
                     $vm_val = null;
                     if ($qr_hier->nextHit()) {
                         $vm_val = $qr_hier->get($vs_hier_fld_name, $pa_options);
                     }
                     if ($vm_val) {
                         $va_hiers[] = $vb_return_as_array ? array_shift($vm_val) : $vm_val;
                     }
                 }
                 return $vb_return_as_array ? $va_hiers : join($vs_delimiter, $va_hiers);
                 break;
             case 'hierarchy':
                 // generate the hierarchy
                 if ($va_path_components['related']) {
                     // [RELATED TABLE HIERARCHY]
                     if (!isset(SearchResult::$opa_hierarchy_parent_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']])) {
                         $this->prefetchHierarchyParents($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     // ids of related items
                     $va_ids = array_values(SearchResult::$opa_hierarchy_parent_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']]);
                 } else {
                     // [PRIMARY TABLE HIERARCHY]
                     if (!isset(SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_row_id])) {
                         $this->prefetchHierarchyParents($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     $va_ids = array($vn_row_id);
                 }
                 if (!sizeof($va_ids)) {
                     return $pa_options['returnAsArray'] ? array() : null;
                 }
                 $vs_hier_pk_fld = $t_instance->primaryKey();
                 $va_hiers = $va_hier_ids = array();
                 $vs_hierarchy_direction = isset($pa_options['hierarchyDirection']) ? strtolower($pa_options['hierarchyDirection']) : 'asc';
                 if ($t_instance->isHierarchical()) {
                     if ($va_path_components['field_name'] === $vs_hier_pk_fld) {
                         if ($va_path_components['related']) {
                             foreach ($va_ids as $vn_id) {
                                 if (is_array(SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_id])) {
                                     $va_hier_id_list = array_merge(array($vn_id), SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_id]);
                                     $va_hier_id_list = array_filter($va_hier_id_list, function ($v) {
                                         return $v > 0;
                                     });
                                     if ($vs_hierarchy_direction === 'asc') {
                                         $va_hier_id_list = array_reverse($va_hier_id_list);
                                     }
                                     if (!is_null($vn_max_levels_from_top)) {
                                         $va_hier_id_list = array_slice($va_hier_id_list, 0, $vn_max_levels_from_top, true);
                                     } elseif (!is_null($vn_max_levels_from_bottom)) {
                                         if (($vn_start = sizeof($va_hier_id_list) - $vn_max_levels_from_bottom) < 0) {
                                             $vn_start = 0;
                                         }
                                         $va_hier_id_list = array_slice($va_hier_id_list, $vn_start, $vn_max_levels_from_bottom, true);
                                     }
                                     $va_hier_ids[] = $va_hier_id_list;
                                 }
                             }
                         } else {
                             // Return ids from hierarchy in order
                             if (is_array(SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_row_id])) {
                                 $va_hier_ids = array_merge(array($vn_row_id), SearchResult::$opa_hierarchy_parent_prefetch_cache[$va_path_components['table_name']][$vn_row_id]);
                             } else {
                                 $va_hier_ids = array($vn_row_id);
                             }
                             if (!is_null($vn_max_levels_from_top)) {
                                 $va_hier_ids = array_slice($va_hier_ids, 0, $vn_max_levels_from_top, true);
                             } elseif (!is_null($vn_max_levels_from_bottom)) {
                                 if (($vn_start = sizeof($va_hier_ids) - $vn_max_levels_from_bottom) < 0) {
                                     $vn_start = 0;
                                 }
                                 $va_hier_ids = array_slice($va_hier_ids, $vn_start, $vn_max_levels_from_bottom, true);
                             }
                             if ($vs_hierarchy_direction === 'asc') {
                                 $va_hier_ids = array_reverse($va_hier_ids);
                             }
                         }
                         return $vb_return_as_array ? $va_hier_ids : join($vs_delimiter, $va_hier_ids);
                     } else {
                         $vs_field_spec = join('.', array_values($va_path_components['components']));
                         $va_ancestor_id_list = $this->get($va_path_components['table_name'] . '.hierarchy.' . $vs_hier_pk_fld, array_merge($pa_options, array('returnAsArray' => true, 'returnAsLink' => false, 'returnAllLocales' => false)));
                         if (!is_array($va_ancestor_id_list)) {
                             return $vb_return_as_array ? array() : null;
                         }
                         if (!$va_path_components['related']) {
                             $va_ancestor_id_list = array($va_ancestor_id_list);
                         }
                         $va_hier_list = array();
                         foreach ($va_ancestor_id_list as $va_ancestor_ids) {
                             if ($vn_remove_first_items > 0) {
                                 $va_ancestor_ids = array_slice($va_ancestor_ids, $vn_remove_first_items);
                             }
                             $va_hier_item = array();
                             if ($qr_hier = caMakeSearchResult($va_path_components['table_name'], $va_ancestor_ids)) {
                                 while ($qr_hier->nextHit()) {
                                     $va_hier_item += $qr_hier->get($vs_field_spec, array('returnWithStructure' => true, 'returnAllLocales' => true, 'useLocaleCodes' => $pa_options['useLocaleCodes']));
                                 }
                                 if (!is_null($vn_max_levels_from_top)) {
                                     $va_hier_item = array_slice($va_hier_item, 0, $vn_max_levels_from_top, true);
                                 } elseif (!is_null($vn_max_levels_from_bottom)) {
                                     if (($vn_start = sizeof($va_hier_item) - $vn_max_levels_from_bottom) < 0) {
                                         $vn_start = 0;
                                     }
                                     $va_hier_item = array_slice($va_hier_item, $vn_start, $vn_max_levels_from_bottom, true);
                                 }
                                 $va_hier_list[] = $va_hier_item;
                             }
                         }
                     }
                 }
                 $va_acc = array();
                 foreach ($va_hier_list as $vn_h => $va_hier_item) {
                     if (!$vb_return_all_locales) {
                         $va_hier_item = caExtractValuesByUserLocale($va_hier_item);
                     }
                     if ($vb_return_with_structure) {
                         $va_acc[] = $va_hier_item;
                     } else {
                         $va_acc = $this->_flattenArray($va_hier_item, $pa_options);
                     }
                 }
                 return $pa_options['returnAsArray'] ? $va_acc : join($vs_delimiter, $va_acc);
                 break;
             case 'children':
                 // grab children
                 if ($va_path_components['related']) {
                     // [RELATED TABLE CHILDREN]
                     if (!isset(SearchResult::$opa_hierarchy_children_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']])) {
                         $this->prefetchHierarchyChildren($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     $va_ids = SearchResult::$opa_hierarchy_children_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']];
                 } else {
                     // [PRIMARY TABLE CHILDREN]
                     if (!isset(SearchResult::$opa_hierarchy_children_prefetch_cache[$this->ops_table_name][$vn_row_id])) {
                         $this->prefetchHierarchyChildren($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     $va_ids = array($vn_row_id);
                 }
                 $va_hier_list = array();
                 foreach ($va_ids as $vn_id) {
                     if (!is_array(SearchResult::$opa_hierarchy_children_prefetch_cache[$va_path_components['table_name']][$vn_id]) || !sizeof(SearchResult::$opa_hierarchy_children_prefetch_cache[$va_path_components['table_name']][$vn_id])) {
                         continue;
                     }
                     $qr_hier = $t_instance->makeSearchResult($va_path_components['table_name'], SearchResult::$opa_hierarchy_children_prefetch_cache[$va_path_components['table_name']][$vn_id]);
                     $va_tmp = array($va_path_components['table_name']);
                     if ($va_path_components['field_name']) {
                         $va_tmp[] = $va_path_components['field_name'];
                     }
                     if ($va_path_components['subfield_name']) {
                         $va_tmp[] = $va_path_components['subfield_name'];
                     }
                     $vs_hier_fld_name = join(".", $va_tmp);
                     $vs_pk = $t_instance->primaryKey();
                     while ($qr_hier->nextHit()) {
                         $vm_val = $qr_hier->get($vs_hier_fld_name, $pa_options);
                         $va_hier_list[$qr_hier->get($va_path_components['table_name'] . '.' . $vs_pk)] = $vb_return_as_array ? array_shift($vm_val) : $vm_val;
                     }
                 }
                 if (!$vb_return_as_array) {
                     return join($vs_delimiter, $va_hier_list);
                 }
                 return $va_hier_list;
                 break;
             case 'siblings':
                 // grab siblings
                 if ($va_path_components['related']) {
                     // [RELATED TABLE SIBLINGS]
                     if (!isset(SearchResult::$opa_hierarchy_siblings_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']])) {
                         $this->prefetchHierarchySiblings($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     $va_ids = SearchResult::$opa_hierarchy_siblings_prefetch_cache_index[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']];
                 } else {
                     // [PRIMARY TABLE SIBLINGS]
                     if (!isset(SearchResult::$opa_hierarchy_siblings_prefetch_cache[$this->ops_table_name][$vn_row_id])) {
                         $this->prefetchHierarchySiblings($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                     }
                     $va_ids = array($vn_row_id);
                 }
                 $va_hier_list = array();
                 foreach ($va_ids as $vn_id) {
                     if (!is_array(SearchResult::$opa_hierarchy_siblings_prefetch_cache[$va_path_components['table_name']][$vn_id]) || !sizeof(SearchResult::$opa_hierarchy_siblings_prefetch_cache[$va_path_components['table_name']][$vn_id])) {
                         continue;
                     }
                     $qr_hier = $t_instance->makeSearchResult($va_path_components['table_name'], SearchResult::$opa_hierarchy_siblings_prefetch_cache[$va_path_components['table_name']][$vn_id]);
                     $va_tmp = array($va_path_components['table_name']);
                     if ($va_path_components['field_name']) {
                         $va_tmp[] = $va_path_components['field_name'];
                     }
                     if ($va_path_components['subfield_name']) {
                         $va_tmp[] = $va_path_components['subfield_name'];
                     }
                     $vs_hier_fld_name = join(".", $va_tmp);
                     $vs_pk = $t_instance->primaryKey();
                     while ($qr_hier->nextHit()) {
                         $vm_val = $qr_hier->get($vs_hier_fld_name, $pa_options);
                         $va_hier_list[$qr_hier->get($va_path_components['table_name'] . '.' . $vs_pk)] = $vb_return_as_array ? array_shift($vm_val) : $vm_val;
                     }
                 }
                 if (!$vb_return_as_array) {
                     return join($vs_delimiter, $va_hier_list);
                 }
                 return $va_hier_list;
                 break;
         }
         return;
     }
     if ($va_path_components['related']) {
         //
         // [RELATED TABLE]
         //
         $vs_opt_md5 = caMakeCacheKeyFromOptions(array_merge($pa_options, array('dontReturnLabels' => false)));
         if (!isset(self::$s_rel_prefetch_cache[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']][$vs_opt_md5])) {
             $this->prefetchRelated($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), array_merge($pa_options, array('dontReturnLabels' => false)));
         }
         $va_related_items = self::$s_rel_prefetch_cache[$this->ops_table_name][$vn_row_id][$va_path_components['table_name']][$vs_opt_md5];
         if (!is_array($va_related_items)) {
             return $vb_return_with_structure || $vb_return_as_array ? array() : null;
         }
         return $this->_getRelatedValue($va_related_items, $va_val_opts);
     } else {
         if (!$va_path_components['hierarchical_modifier']) {
             //
             // [PRIMARY TABLE] Created on
             //
             if ($va_path_components['field_name'] == 'created') {
                 if (!isset(self::$s_timestamp_cache['created_on'][$this->ops_table_name][$vn_row_id])) {
                     $this->prefetchChangeLogData($this->ops_table_name, $this->opo_engine_result->currentRow(), $this->getOption('prefetch'));
                 }
                 if ($vb_return_as_array) {
                     return self::$s_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 = self::$s_timestamp_cache['created_on'][$this->ops_table_name][$vn_row_id][$vs_subfield];
                     if ($vs_subfield == 'timestamp') {
                         $this->opo_tep->init();
                         $this->opo_tep->setUnixTimestamps($vm_val, $vm_val);
                         $vm_val = $this->opo_tep->getText($pa_options);
                     }
                     return $vm_val;
                 }
             }
             //
             // [PRIMARY TABLE] Last modified on
             //
             if ($va_path_components['field_name'] == 'lastModified') {
                 if (!isset(self::$s_timestamp_cache['last_changed'][$this->ops_table_name][$vn_row_id])) {
                     $this->prefetchChangeLogData($this->ops_table_name, $this->opo_engine_result->currentRow(), $this->getOption('prefetch'));
                 }
                 if ($vb_return_as_array) {
                     return self::$s_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 = self::$s_timestamp_cache['last_changed'][$this->ops_table_name][$vn_row_id][$vs_subfield];
                     if ($vs_subfield == 'timestamp') {
                         $this->opo_tep->init();
                         $this->opo_tep->setUnixTimestamps($vm_val, $vm_val);
                         $vm_val = $this->opo_tep->getText($pa_options);
                     }
                     return $vm_val;
                 }
             }
             $vs_opt_md5 = caMakeCacheKeyFromOptions($pa_options);
             //
             // [PRIMARY TABLE] Preferred/nonpreferred labels
             //
             if (in_array($va_path_components['field_name'], array('preferred_labels', 'nonpreferred_labels')) && $t_instance instanceof LabelableBaseModelWithAttributes) {
                 $vs_label_table_name = $t_instance->getLabelTableName();
                 if (!isset(self::$s_prefetch_cache[$vs_label_table_name][$vn_row_id][$vs_opt_md5])) {
                     $this->prefetchLabels($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                 }
                 return $this->_getLabelValue(self::$s_prefetch_cache[$vs_label_table_name][$vn_row_id][$vs_opt_md5], $t_instance, $va_val_opts);
             }
             if ($t_instance->hasField($va_path_components['field_name'])) {
                 $va_val_opts['fieldInfo'] = $t_instance->getFieldInfo($va_path_components['field_name']);
                 //
                 // [PRIMARY TABLE] Plain old intrinsic
                 //
                 if (!isset(self::$s_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5])) {
                     $this->prefetch($va_path_components['table_name'], $this->opo_engine_result->currentRow(), $this->getOption('prefetch'), $pa_options);
                 }
                 return $this->_getIntrinsicValue(self::$s_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5], $t_instance, $va_val_opts);
             } elseif (method_exists($t_instance, 'isValidBundle') && !$t_instance->hasElement($va_path_components['field_name']) && $t_instance->isValidBundle($va_path_components['field_name'])) {
                 //
                 // [PRIMARY TABLE] Special bundle
                 //
                 return $t_instance->renderBundleForDisplay($va_path_components['field_name'], $vn_row_id, self::$s_prefetch_cache[$va_path_components['table_name']][$vn_row_id][$vs_opt_md5], $va_val_opts);
             } else {
                 //
                 // [PRIMARY TABLE] Metadata attribute
                 //
                 if ($t_instance instanceof BaseModelWithAttributes && isset($va_path_components['field_name']) && $va_path_components['field_name'] && ($t_element = $t_instance->_getElementInstance($va_path_components['field_name']))) {
                     $vn_element_id = $t_element->getPrimaryKey();
                 } else {
                     return $pa_options['returnAsArray'] ? array() : null;
                 }
                 if (!isset(ca_attributes::$s_get_attributes_cache[(int) $this->opn_table_num . '/' . (int) $vn_row_id][(int) $vn_element_id])) {
                     ca_attributes::prefetchAttributes($this->opo_subject_instance->getDb(), $this->opn_table_num, $this->getRowIDsToPrefetch($this->opo_engine_result->currentRow(), $this->getOption('prefetch')), $vn_element_id ? array($vn_element_id) : null, array('dontFetchAlreadyCachedValues' => true));
                 }
                 $va_attributes = ca_attributes::getAttributes($this->opo_subject_instance->getDb(), $this->opn_table_num, $vn_row_id, array($vn_element_id), array());
                 return $this->_getAttributeValue($va_attributes[$vn_element_id], $t_instance, $va_val_opts);
             }
         }
     }
     return null;
 }
Esempio n. 6
0
 /**
  * Returns all available search form placements - those data bundles that can be searches for the given content type, in other words.
  * The returned value is a list of arrays; each array contains a 'bundle' specifier than can be passed got Model::get() or SearchResult::get() and a display name
  *
  * @param mixed $pm_table_name_or_num The table name or number specifying the content type to fetch bundles for. If omitted the content table of the currently loaded search form will be used.
  * @return array And array of bundles keyed on display label. Each value is an array with these keys:
  *		bundle = The bundle name (eg. ca_objects.idno)
  *		display = Display label for each available bundle
  *		description = Description of bundle
  * 
  * Will return null if table name or number is invalid.
  */
 public function getAvailableBundles($pm_table_name_or_num = null, $pa_options = null)
 {
     if (!$pm_table_name_or_num) {
         $pm_table_name_or_num = $this->get('table_num');
     }
     $pm_table_name_or_num = $this->_DATAMODEL->getTableNum($pm_table_name_or_num);
     if (!$pm_table_name_or_num) {
         return null;
     }
     $t_instance = $this->_DATAMODEL->getInstanceByTableNum($pm_table_name_or_num, true);
     $va_search_settings = $this->opo_search_indexing_config->getAssoc($this->_DATAMODEL->getTableName($pm_table_name_or_num));
     $vs_primary_table = $t_instance->tableName();
     $vs_table_display_name = $t_instance->getProperty('NAME_PLURAL');
     $t_placement = new ca_search_form_placements(null, array());
     $va_available_bundles = array();
     $va_additional_settings = array('width' => array('formatType' => FT_TEXT, 'displayType' => DT_FIELD, 'width' => 4, 'height' => 1, 'takesLocale' => false, 'default' => "100px", 'label' => _t('Width'), 'description' => _t('Width, in characters, of search form elements.')));
     $t_placement->setSettingDefinitionsForPlacement($va_additional_settings);
     // Full-text
     $vs_bundle = "_fulltext";
     $vs_display = "<div id='searchFormEditor__fulltext'><span class='bundleDisplayEditorPlacementListItemTitle'>" . _t("General") . '</span> ' . ($vs_label = _t('Full text')) . "</div>";
     $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'label' => $vs_label, 'display' => $vs_display, 'description' => $vs_description = _t('Searches on all content that has been indexed'), 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => $va_additional_settings);
     TooltipManager::add("#searchFormEditor__fulltext", "<h2>{$vs_label}</h2>{$vs_description}");
     // get fields
     foreach ($va_search_settings as $vs_table => $va_fields) {
         if (!is_array($va_fields['fields'])) {
             continue;
         }
         if ($vs_table == $vs_primary_table) {
             $va_element_codes = method_exists($t_instance, 'getApplicableElementCodes') ? $t_instance->getApplicableElementCodes(null, false, false) : array();
             $va_field_list = array();
             foreach ($va_fields['fields'] as $vs_field => $va_field_indexing_info) {
                 if ($vs_field === '_metadata') {
                     foreach ($va_element_codes as $vs_code) {
                         $va_field_list[$vs_code] = array();
                     }
                 } else {
                     $va_field_list[$vs_field] = $va_field_indexing_info;
                 }
             }
             foreach ($va_field_list as $vs_field => $va_field_indexing_info) {
                 if (in_array('DONT_INCLUDE_IN_SEARCH_FORM', $va_field_indexing_info)) {
                     continue;
                 }
                 if (!($va_field_info = $t_instance->getFieldInfo($vs_field))) {
                     // is it an attribute?
                     if (in_array($vs_field, $va_element_codes)) {
                         $t_element = $this->_getElementInstance($vs_field);
                         if (!$t_element) {
                             continue;
                         }
                         if (in_array($t_element->get('datatype'), array(15, 16))) {
                             continue;
                         }
                         // skip file and media attributes - never searchable
                         if (!$t_element->getSetting('canBeUsedInSearchForm')) {
                             continue;
                         }
                         if (caGetBundleAccessLevel($vs_primary_table, $vs_field) == __CA_BUNDLE_ACCESS_NONE__) {
                             continue;
                         }
                         $vs_bundle = $vs_table . '.' . $vs_field;
                         $vs_display = "<div id='searchFormEditor_{$vs_table}_{$vs_field}'><span class='bundleDisplayEditorPlacementListItemTitle'>" . caUcFirstUTF8Safe($t_instance->getProperty('NAME_SINGULAR')) . "</span> " . ($vs_label = $t_instance->getDisplayLabel($vs_bundle)) . "</div>";
                         $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'label' => $vs_label, 'display' => $vs_display, 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle), 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => $va_additional_settings);
                         TooltipManager::add("#searchFormEditor_{$vs_table}_{$vs_field}", "<h2>{$vs_label}</h2>{$vs_description}");
                     }
                 } else {
                     if (isset($va_field_info['DONT_USE_AS_BUNDLE']) && $va_field_info['DONT_USE_AS_BUNDLE']) {
                         continue;
                     }
                     if (in_array($va_field_info['FIELD_TYPE'], array(FT_MEDIA, FT_FILE))) {
                         continue;
                     }
                     $vs_bundle = $vs_table . '.' . $vs_field;
                     $vs_display = "<div id='searchFormEditor_{$vs_table}_{$vs_field}'><span class='bundleDisplayEditorPlacementListItemTitle'>" . caUcFirstUTF8Safe($t_instance->getProperty('NAME_SINGULAR')) . "</span> " . ($vs_label = $t_instance->getDisplayLabel($vs_bundle)) . "</div>";
                     $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'label' => $vs_label, 'display' => $vs_display, 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle), 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => $va_additional_settings);
                     TooltipManager::add("#searchFormEditor_{$vs_table}_{$vs_field}", "<h2>{$vs_label}</h2>{$vs_description}");
                 }
             }
         } else {
             // related table
             if ($this->getAppConfig()->get($vs_table . '_disable')) {
                 continue;
             }
             $t_table = $this->_DATAMODEL->getInstanceByTableName($vs_table, true);
             if (method_exists($t_table, "getSubjectTableName") && ($vs_subject_table = $t_table->getSubjectTableName())) {
                 if ($this->getAppConfig()->get($vs_subject_table . '_disable')) {
                     continue;
                 }
             }
             if (caGetBundleAccessLevel($vs_primary_table, $vs_subject_table) == __CA_BUNDLE_ACCESS_NONE__) {
                 continue;
             }
             foreach ($va_fields['fields'] as $vs_field => $va_field_indexing_info) {
                 if (in_array('DONT_INCLUDE_IN_SEARCH_FORM', $va_field_indexing_info)) {
                     continue;
                 }
                 if ($va_field_info = $t_table->getFieldInfo($vs_field)) {
                     if (isset($va_field_info['DONT_USE_AS_BUNDLE']) && $va_field_info['DONT_USE_AS_BUNDLE']) {
                         continue;
                     }
                     $vs_bundle = $vs_table . '.' . $vs_field;
                     $vs_related_table = caUcFirstUTF8Safe($t_table->getProperty('NAME_SINGULAR'));
                     if (method_exists($t_table, 'getSubjectTableInstance')) {
                         $t_subject = $t_table->getSubjectTableInstance();
                         $vs_related_table = caUcFirstUTF8Safe($t_subject->getProperty('NAME_SINGULAR'));
                     }
                     $vs_label = $t_instance->getDisplayLabel($vs_bundle);
                     if (method_exists($t_table, "getSubjectTableName") && $vs_primary_table == $vs_subject_table) {
                         $vs_display = "<div id='searchFormEditor_{$vs_table}_{$vs_field}'><span class='bundleDisplayEditorPlacementListItemTitle'>" . caUcFirstUTF8Safe($t_subject->getProperty('NAME_SINGULAR')) . "</span> {$vs_label}</div>";
                     } else {
                         $vs_display = "<div id='searchFormEditor_{$vs_table}_{$vs_field}'><span class='bundleDisplayEditorPlacementListItemTitle'>{$vs_related_table}</span> {$vs_label}</div>";
                     }
                     $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'label' => $vs_label, 'display' => $vs_display, 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle), 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => $va_additional_settings);
                     TooltipManager::add("#searchFormEditor_{$vs_table}_{$vs_field}", "<h2>{$vs_label}</h2>{$vs_description}");
                 }
             }
         }
     }
     //
     // access points
     //
     $va_access_points = isset($va_search_settings['_access_points']) && is_array($va_search_settings['_access_points']) ? $va_search_settings['_access_points'] : array();
     //unset($va_search_settings['_access_points']);
     foreach ($va_access_points as $vs_access_point => $va_access_point_info) {
         if (isset($va_access_point_info['options']) && is_array($va_access_point_info['options'])) {
             if (in_array('DONT_INCLUDE_IN_SEARCH_FORM', $va_access_point_info['options'])) {
                 continue;
             }
         }
         $vs_display = "<div id='searchFormEditor_{$vs_access_point}'><span class='bundleDisplayEditorPlacementListItemTitle'>" . _t('Access point') . '</span> ' . ($vs_label = isset($va_access_point_info['name']) && $va_access_point_info['name'] ? $va_access_point_info['name'] : $vs_access_point) . "</div>";
         $va_available_bundles[strip_tags($vs_display)][$vs_access_point] = array('bundle' => $vs_access_point, 'label' => $vs_label, 'display' => $vs_display, 'description' => $vs_description = isset($va_access_point_info['description']) && $va_access_point_info['description'] ? $va_access_point_info['description'] : '', 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_access_point . '_0')), 'settings' => $va_additional_settings);
         TooltipManager::add("#searchFormEditor_{$vs_access_point}", "<h2>{$vs_label}</h2>{$vs_description}");
     }
     //
     // created and modified
     //
     $t_placement->setSettingDefinitionsForPlacement($va_additional_settings);
     foreach (array('created', 'modified') as $vs_bundle) {
         $vs_display = "<div id='searchFormEditor_{$vs_bundle}'><span class='bundleDisplayEditorPlacementListItemTitle'>" . _t('General') . "</span> " . ($vs_label = $t_instance->getDisplayLabel($vs_bundle)) . "</div>";
         $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array('bundle' => $vs_bundle, 'label' => $vs_label, 'display' => $vs_display, 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle), 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle . '_0')), 'settings' => $va_additional_settings);
         TooltipManager::add("#searchFormEditor_{$vs_bundle}", "<h2>{$vs_label}</h2>{$vs_description}");
     }
     ksort($va_available_bundles);
     $va_sorted_bundles = array();
     foreach ($va_available_bundles as $vs_k => $va_val) {
         foreach ($va_val as $vs_real_key => $va_info) {
             $va_sorted_bundles[$vs_real_key] = $va_info;
         }
     }
     return $va_sorted_bundles;
 }
 /**
  * Returns information about representations linked to the currently loaded item. Use this if you want to get the urls, tags and other information for all representations associated with a given item.
  *
  * @param array $pa_versions An array of media versions to include information for. If you omit this then a single version, 'preview170', is assumed by default.
  * @param array $pa_version_sizes Optional array of sizes to force specific versions to. The array keys are version names; the values are arrays with two keys: 'width' and 'height'; if present these values will be used in lieu of the actual values in the database
  * @param array $pa_options An optional array of options to use when getting representation information. Supported options are:
  *		return_primary_only - If true then only the primary representation will be returned
  *		return_with_access - Set to an array of access values to filter representation through; only representations with an access value in the list will be returned
  *		checkAccess - synonym for return_with_access
  *		.. and options supported by getMediaTag() .. [they are passed through]
  *	
  * @return array An array of information about the linked representations
  */
 public function getRepresentations($pa_versions = null, $pa_version_sizes = null, $pa_options = null)
 {
     if (!($vn_id = $this->getPrimaryKey())) {
         return null;
     }
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     if (caGetBundleAccessLevel($this->tableName(), 'ca_object_representations') == __CA_BUNDLE_ACCESS_NONE__) {
         return null;
     }
     if (!is_array($pa_versions)) {
         $pa_versions = array('preview170');
     }
     if (isset($pa_options['return_primary_only']) && $pa_options['return_primary_only']) {
         $vs_is_primary_sql = ' AND (caoor.is_primary = 1)';
     } else {
         $vs_is_primary_sql = '';
     }
     if ($pa_options['checkAccess']) {
         $pa_options['return_with_access'] = $pa_options['checkAccess'];
     }
     if (is_array($pa_options['return_with_access']) && sizeof($pa_options['return_with_access']) > 0) {
         $vs_access_sql = ' AND (caor.access IN (' . join(", ", $pa_options['return_with_access']) . '))';
     } else {
         $vs_access_sql = '';
     }
     $o_db = $this->getDb();
     if (!($vs_linking_table = RepresentableBaseModel::getRepresentationRelationshipTableName($this->tableName()))) {
         return null;
     }
     $vs_pk = $this->primaryKey();
     $qr_reps = $o_db->query("\n\t\t\t\tSELECT caor.representation_id, caor.media, caoor.is_primary, caor.access, caor.status, l.name, caor.locale_id, caor.media_metadata, caor.type_id, caor.idno, caor.idno_sort, caor.md5, caor.mimetype, caor.original_filename, caoor.rank\n\t\t\t\tFROM ca_object_representations caor\n\t\t\t\tINNER JOIN {$vs_linking_table} AS caoor ON caor.representation_id = caoor.representation_id\n\t\t\t\tLEFT JOIN ca_locales AS l ON caor.locale_id = l.locale_id\n\t\t\t\tWHERE\n\t\t\t\t\tcaoor.{$vs_pk} = ? AND deleted = 0\n\t\t\t\t\t{$vs_is_primary_sql}\n\t\t\t\t\t{$vs_access_sql}\n\t\t\t\tORDER BY\n\t\t\t\t\tcaoor.rank, caoor.is_primary DESC\n\t\t\t", (int) $vn_id);
     $va_reps = array();
     $t_rep = new ca_object_representations();
     while ($qr_reps->nextRow()) {
         $vn_rep_id = $qr_reps->get('representation_id');
         $va_tmp = $qr_reps->getRow();
         $va_tmp['tags'] = array();
         $va_tmp['urls'] = array();
         $va_info = $qr_reps->getMediaInfo('media');
         $va_tmp['info'] = array('original_filename' => $va_info['ORIGINAL_FILENAME']);
         foreach ($pa_versions as $vs_version) {
             if (is_array($pa_version_sizes) && isset($pa_version_sizes[$vs_version])) {
                 $vn_width = $pa_version_sizes[$vs_version]['width'];
                 $vn_height = $pa_version_sizes[$vs_version]['height'];
             } else {
                 $vn_width = $vn_height = 0;
             }
             if ($vn_width && $vn_height) {
                 $va_tmp['tags'][$vs_version] = $qr_reps->getMediaTag('media', $vs_version, array_merge($pa_options, array('viewer_width' => $vn_width, 'viewer_height' => $vn_height)));
             } else {
                 $va_tmp['tags'][$vs_version] = $qr_reps->getMediaTag('media', $vs_version, $pa_options);
             }
             $va_tmp['urls'][$vs_version] = $qr_reps->getMediaUrl('media', $vs_version);
             $va_tmp['paths'][$vs_version] = $qr_reps->getMediaPath('media', $vs_version);
             $va_tmp['info'][$vs_version] = $qr_reps->getMediaInfo('media', $vs_version);
             $va_tmp['dimensions'][$vs_version] = caGetRepresentationDimensionsForDisplay($qr_reps, 'original', array());
         }
         if (isset($va_info['INPUT']['FETCHED_FROM']) && ($vs_fetched_from_url = $va_info['INPUT']['FETCHED_FROM'])) {
             $va_tmp['fetched_from'] = $vs_fetched_from_url;
             $va_tmp['fetched_on'] = (int) $va_info['INPUT']['FETCHED_ON'];
         }
         $va_tmp['num_multifiles'] = $t_rep->numFiles($vn_rep_id);
         $va_reps[$vn_rep_id] = $va_tmp;
     }
     $va_labels = $t_rep->getPreferredDisplayLabelsForIDs(array_keys($va_reps));
     foreach ($va_labels as $vn_rep_id => $vs_label) {
         $va_reps[$vn_rep_id]['label'] = $vs_label;
     }
     return $va_reps;
 }
Esempio n. 8
0
 /**
  * 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;
 }
Esempio n. 9
0
/**
 * Returns all available search form placements - those data bundles that can be searches for the given content type, in other words.
 * The returned value is a list of arrays; each array contains a 'bundle' specifier than can be passed got Model::get() or SearchResult::get() and a display name
 *
 * @param mixed $pm_table_name_or_num The table name or number specifying the content type to fetch bundles for. If omitted the content table of the currently loaded search form will be used.
 * @return array And array of bundles keyed on display label. Each value is an array with these keys:
 *		bundle = The bundle name (eg. ca_objects.idno)
 *		display = Display label for each available bundle
 *		description = Description of bundle
 * 
 * Will return null if table name or number is invalid.
 */
function caGetBundlesAvailableForSearch($pm_table_name_or_num, $pa_options = null)
{
    $pb_for_select = caGetOption('forSelect', $pa_options, false);
    $pa_filter = caGetOption('filter', $pa_options, null);
    $o_dm = Datamodel::load();
    $o_config = Configuration::load();
    $o_indexing_config = caGetSearchIndexingConfig();
    $pm_table_name_or_num = $o_dm->getTableNum($pm_table_name_or_num);
    if (!$pm_table_name_or_num) {
        return null;
    }
    $t_instance = $o_dm->getInstanceByTableNum($pm_table_name_or_num, true);
    $va_search_settings = $o_indexing_config->getAssoc($o_dm->getTableName($pm_table_name_or_num));
    $vs_primary_table = $t_instance->tableName();
    $vs_table_display_name = $t_instance->getProperty('NAME_PLURAL');
    $va_available_bundles = array();
    // Full-text
    $vs_bundle = "_fulltext";
    if (!(is_array($pa_filter) && sizeof($pa_filter) && !in_array($vs_bundle, $pa_filter))) {
        $vs_label = _t('Full text');
        $va_available_bundles[$vs_label][$vs_bundle] = array('bundle' => $vs_bundle, 'label' => $vs_label, 'description' => $vs_description = _t('Searches on all content that has been indexed'));
    }
    // rewrite label filters to use label tables actually used in indexing config
    if (is_array($pa_filter)) {
        foreach ($pa_filter as $vn_i => $vs_filter) {
            $va_tmp = explode('.', $vs_filter);
            if (in_array($va_tmp[1], array('preferred_labels', 'nonpreferred_labels'))) {
                if ($t_filter_instance = $o_dm->getInstanceByTableName($va_tmp[0], true)) {
                    $pa_filter[] = $t_filter_instance->getLabelTableName() . ($va_tmp[2] ? '.' . $va_tmp[2] : '');
                }
            }
        }
    }
    // get fields
    foreach ($va_search_settings as $vs_table => $va_fields) {
        if (!is_array($va_fields['fields'])) {
            continue;
        }
        if ($vs_table == $vs_primary_table) {
            $va_element_codes = method_exists($t_instance, 'getApplicableElementCodes') ? $t_instance->getApplicableElementCodes(null, false, false) : array();
            $va_field_list = array();
            foreach ($va_fields['fields'] as $vs_field => $va_field_indexing_info) {
                if ($vs_field === '_metadata') {
                    foreach ($va_element_codes as $vs_code) {
                        $va_field_list[$vs_code] = array();
                    }
                } else {
                    $va_field_list[$vs_field] = $va_field_indexing_info;
                }
            }
            foreach ($va_field_list as $vs_field => $va_field_indexing_info) {
                if (in_array('DONT_INCLUDE_IN_SEARCH_FORM', $va_field_indexing_info)) {
                    continue;
                }
                if (is_array($pa_filter) && sizeof($pa_filter) && !in_array($vs_table . '.' . $vs_field, $pa_filter)) {
                    continue;
                }
                if (!($va_field_info = $t_instance->getFieldInfo($vs_field))) {
                    // is it an attribute?
                    if (in_array($vs_field, $va_element_codes)) {
                        $t_element = $t_instance->_getElementInstance($vs_field);
                        if (!$t_element) {
                            continue;
                        }
                        if (in_array($t_element->get('datatype'), array(15, 16))) {
                            continue;
                        }
                        // skip file and media attributes - never searchable
                        if (!$t_element->getSetting('canBeUsedInSearchForm')) {
                            continue;
                        }
                        if (caGetBundleAccessLevel($vs_primary_table, $vs_field) == __CA_BUNDLE_ACCESS_NONE__) {
                            continue;
                        }
                        $vs_bundle = $vs_table . '.' . $vs_field;
                        $vs_label = $t_instance->getDisplayLabel($vs_bundle);
                        $va_available_bundles[$vs_label][$vs_bundle] = array('bundle' => $vs_bundle, 'label' => $vs_label, 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle));
                    }
                } else {
                    if (isset($va_field_info['DONT_USE_AS_BUNDLE']) && $va_field_info['DONT_USE_AS_BUNDLE']) {
                        continue;
                    }
                    if (in_array($va_field_info['FIELD_TYPE'], array(FT_MEDIA, FT_FILE))) {
                        continue;
                    }
                    $vs_bundle = $vs_table . '.' . $vs_field;
                    $vs_label = $t_instance->getDisplayLabel($vs_bundle);
                    $va_available_bundles[$vs_label][$vs_bundle] = array('bundle' => $vs_bundle, 'label' => $vs_label, 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle));
                }
            }
        } else {
            // related table
            if ($o_config->get($vs_table . '_disable')) {
                continue;
            }
            $t_table = $o_dm->getInstanceByTableName($vs_table, true);
            if (method_exists($t_table, "getSubjectTableName") && ($vs_subject_table = $t_table->getSubjectTableName())) {
                if ($o_config->get($vs_subject_table . '_disable')) {
                    continue;
                }
            }
            if (caGetBundleAccessLevel($vs_primary_table, $vs_subject_table) == __CA_BUNDLE_ACCESS_NONE__) {
                continue;
            }
            foreach ($va_fields['fields'] as $vs_field => $va_field_indexing_info) {
                if (in_array('DONT_INCLUDE_IN_SEARCH_FORM', $va_field_indexing_info)) {
                    continue;
                }
                if (is_array($pa_filter) && sizeof($pa_filter) && !in_array($vs_table . '.' . $vs_field, $pa_filter)) {
                    continue;
                }
                if ($va_field_info = $t_table->getFieldInfo($vs_field)) {
                    if (isset($va_field_info['DONT_USE_AS_BUNDLE']) && $va_field_info['DONT_USE_AS_BUNDLE']) {
                        continue;
                    }
                    $vs_bundle = $vs_table . '.' . $vs_field;
                    $vs_related_table = caUcFirstUTF8Safe($t_table->getProperty('NAME_SINGULAR'));
                    if (method_exists($t_table, 'getSubjectTableInstance')) {
                        $t_subject = $t_table->getSubjectTableInstance();
                        $vs_related_table = caUcFirstUTF8Safe($t_subject->getProperty('NAME_SINGULAR'));
                    }
                    $vs_label = $t_instance->getDisplayLabel($vs_bundle);
                    $va_available_bundles[$vs_label][$vs_bundle] = array('bundle' => $vs_bundle, 'label' => $vs_label, 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle));
                }
            }
        }
    }
    //
    // access points
    //
    $va_access_points = isset($va_search_settings['_access_points']) && is_array($va_search_settings['_access_points']) ? $va_search_settings['_access_points'] : array();
    foreach ($va_access_points as $vs_access_point => $va_access_point_info) {
        if (isset($va_access_point_info['options']) && is_array($va_access_point_info['options'])) {
            if (in_array('DONT_INCLUDE_IN_SEARCH_FORM', $va_access_point_info['options'])) {
                continue;
            }
        }
        if (is_array($pa_filter) && sizeof($pa_filter) && !in_array($vs_access_point, $pa_filter)) {
            continue;
        }
        $vs_label = isset($va_access_point_info['name']) && $va_access_point_info['name'] ? $va_access_point_info['name'] : $vs_access_point;
        $va_available_bundles[$vs_label][$vs_access_point] = array('bundle' => $vs_access_point, 'label' => $vs_label, 'description' => $vs_description = isset($va_access_point_info['description']) && $va_access_point_info['description'] ? $va_access_point_info['description'] : '');
    }
    //
    // created and modified
    //
    foreach (array('created', 'modified') as $vs_bundle) {
        if (is_array($pa_filter) && sizeof($pa_filter) && !in_array($vs_bundle, $pa_filter)) {
            continue;
        }
        $vs_label = $t_instance->getDisplayLabel($vs_bundle);
        $va_available_bundles[$vs_label][$vs_bundle] = array('bundle' => $vs_bundle, 'label' => $vs_label, 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle));
    }
    ksort($va_available_bundles);
    $va_sorted_bundles = array();
    foreach ($va_available_bundles as $vs_k => $va_val) {
        foreach ($va_val as $vs_real_key => $va_info) {
            if ($pb_for_select) {
                $va_sorted_bundles[$va_info['label']] = $vs_real_key;
            } else {
                $va_sorted_bundles[$vs_real_key] = $va_info;
            }
        }
    }
    // rewrite bundles to used preferred_labels notation
    if ($pb_for_select) {
        foreach ($va_sorted_bundles as $vs_label => $vs_key) {
            $va_tmp = explode('.', $vs_key);
            if (preg_match('!_labels$!', $va_tmp[0])) {
                if (($t_label_instance = $o_dm->getInstanceByTableName($va_tmp[0], true)) && is_a($t_label_instance, 'BaseLabel')) {
                    $va_sorted_bundles[$vs_label] = $t_label_instance->getSubjectTableName() . '.preferred_labels' . ($va_tmp[1] ? '.' . $va_tmp[1] : '');
                }
            }
        }
    }
    return $va_sorted_bundles;
}