Пример #1
0
/**
 * Generates standard-format inspector panels for editors
 *
 * @param View $po_view Inspector view object
 * @param array $pa_options Optional array of options. Supported options are:
 *		backText = a string to use as the "back" button text; default is "Results"
 *
 * @return string HTML implementing the inspector
 */
function caEditorInspector($po_view, $pa_options = null)
{
    require_once __CA_MODELS_DIR__ . '/ca_sets.php';
    require_once __CA_MODELS_DIR__ . '/ca_data_exporters.php';
    $t_item = $po_view->getVar('t_item');
    $vs_table_name = $t_item->tableName();
    if (($vs_priv_table_name = $vs_table_name) == 'ca_list_items') {
        $vs_priv_table_name = 'ca_lists';
    }
    $vn_item_id = $t_item->getPrimaryKey();
    $o_result_context = $po_view->getVar('result_context');
    $t_ui = $po_view->getVar('t_ui');
    $t_type = method_exists($t_item, "getTypeInstance") ? $t_item->getTypeInstance() : null;
    $vs_type_name = method_exists($t_item, "getTypeName") ? $t_item->getTypeName() : '';
    if (!$vs_type_name) {
        $vs_type_name = $t_item->getProperty('NAME_SINGULAR');
    }
    $va_reps = $po_view->getVar('representations');
    $o_dm = Datamodel::load();
    if ($t_item->isHierarchical()) {
        $va_ancestors = $po_view->getVar('ancestors');
        $vn_parent_id = $t_item->get($t_item->getProperty('HIERARCHY_PARENT_ID_FLD'));
    } else {
        $va_ancestors = array();
        $vn_parent_id = null;
    }
    // action extra to preserve currently open screen across next/previous links
    $vs_screen_extra = $po_view->getVar('screen') ? '/' . $po_view->getVar('screen') : '';
    if ($vs_type_name == "list item") {
        $vs_style = "style='height:auto;'";
    }
    if ($vn_item_id | $po_view->request->getAction() === 'Delete') {
        $vs_buf = '<h3 class="nextPrevious" ' . $vs_style . '>' . caEditorFindResultNavigation($po_view->request, $t_item, $o_result_context, $pa_options) . "</h3>\n";
    }
    $vs_color = null;
    if ($t_type) {
        $vs_color = trim($t_type->get('color'));
    }
    if (!$vs_color && $t_ui) {
        $vs_color = trim($t_ui->get('color'));
    }
    if (!$vs_color) {
        $vs_color = "FFFFFF";
    }
    $vs_buf .= "<h4><div id='caColorbox' style='border: 6px solid #{$vs_color};'>\n";
    $vs_icon = null;
    if ($t_type) {
        $vs_icon = $t_type->getMediaTag('icon', 'icon');
    }
    if (!$vs_icon && $t_ui) {
        $vs_icon = $t_ui->getMediaTag('icon', 'icon');
    }
    if ($vs_icon) {
        $vs_buf .= "<div id='inspectoricon' style='border-right: 6px solid #{$vs_color}; border-bottom: 6px solid #{$vs_color}; -moz-border-radius-bottomright: 8px; -webkit-border-bottom-right-radius: 8px;'>\n{$vs_icon}</div>\n";
    }
    if ($po_view->request->getAction() === 'Delete' && $po_view->request->getParameter('confirm', pInteger)) {
        $vs_buf .= "<strong>" . _t("Deleted %1", $vs_type_name) . "</strong>\n";
        $vs_buf .= "<br style='clear: both;'/></div></h4>\n";
    } else {
        if ($vn_item_id) {
            if (!$po_view->request->config->get("{$vs_priv_table_name}_inspector_disable_headline")) {
                if ($po_view->request->user->canDoAction("can_edit_" . $vs_priv_table_name) && sizeof($t_item->getTypeList()) > 1) {
                    $vs_buf .= "<strong>" . _t("Editing %1", $vs_type_name) . ": </strong>\n";
                } else {
                    $vs_buf .= "<strong>" . _t("Viewing %1", $vs_type_name) . ": </strong>\n";
                }
            }
            if ($t_item->hasField('is_deaccessioned') && $t_item->get('is_deaccessioned') && $t_item->get('deaccession_date', array('getDirectDate' => true)) <= caDateToHistoricTimestamp(_t('now'))) {
                // If currently deaccessioned then display deaccession message
                $vs_buf .= "<br/><div class='inspectorDeaccessioned'>" . _t('Deaccessioned %1', $t_item->get('deaccession_date')) . "</div>\n";
                if ($vs_deaccession_notes = $t_item->get('deaccession_notes')) {
                    TooltipManager::add(".inspectorDeaccessioned", $vs_deaccession_notes);
                }
            } else {
                if ($po_view->request->user->canDoAction('can_see_current_location_in_inspector_ca_objects')) {
                    if ($t_ui && method_exists($t_item, "getObjectHistory") && (is_array($va_placements = $t_ui->getPlacementsForBundle('ca_objects_history')) && sizeof($va_placements) > 0)) {
                        //
                        // Output current "location" of object in life cycle. Configuration is taken from a ca_objects_history bundle configured for the current editor
                        //
                        $va_placement = array_shift($va_placements);
                        $va_bundle_settings = $va_placement['settings'];
                        if (is_array($va_history = $t_item->getObjectHistory($va_bundle_settings, array('limit' => 1, 'currentOnly' => true))) && sizeof($va_history) > 0) {
                            $va_current_location = array_shift(array_shift($va_history));
                            if (!($vs_inspector_current_location_label = $po_view->request->config->get("ca_objects_inspector_current_location_label"))) {
                                $vs_inspector_current_location_label = _t('Current');
                            }
                            if ($va_current_location['display']) {
                                $vs_buf .= "<div class='inspectorCurrentLocation'><strong>" . $vs_inspector_current_location_label . ':</strong><br/>' . $va_current_location['display'] . "</div>";
                            }
                        }
                    } elseif (method_exists($t_item, "getLastLocationForDisplay")) {
                        // If no ca_objects_history bundle is configured then display the last storage location
                        if ($vs_current_location = $t_item->getLastLocationForDisplay("<ifdef code='ca_storage_locations.parent.preferred_labels'>^ca_storage_locations.parent.preferred_labels ➜ </ifdef>^ca_storage_locations.preferred_labels.name")) {
                            $vs_buf .= "<br/><div class='inspectorCurrentLocation'>" . _t('Location: %1', $vs_current_location) . "</div>\n";
                            $vs_full_location_hierarchy = $t_item->getLastLocationForDisplay("^ca_storage_locations.hierarchy.preferred_labels.name%delimiter=_➜_");
                            if ($vs_full_location_hierarchy !== $vs_current_location) {
                                TooltipManager::add(".inspectorCurrentLocation", $vs_full_location_hierarchy);
                            }
                        }
                    }
                }
            }
            //
            // Display flags; expressions for these are defined in app.conf in the <table_name>_inspector_display_flags directive
            //
            if (is_array($va_display_flags = $po_view->request->config->getAssoc("{$vs_table_name}_inspector_display_flags"))) {
                $va_display_flag_buf = array();
                foreach ($va_display_flags as $vs_exp => $vs_display_flag) {
                    $va_exp_vars = array();
                    foreach (ExpressionParser::getVariableList($vs_exp) as $vs_var_name) {
                        $va_exp_vars[$vs_var_name] = $t_item->get($vs_var_name, array('returnIdno' => true));
                    }
                    if (ExpressionParser::evaluate($vs_exp, $va_exp_vars)) {
                        $va_display_flag_buf[] = $t_item->getWithTemplate("{$vs_display_flag}");
                    }
                }
                if (sizeof($va_display_flag_buf) > 0) {
                    $vs_buf .= join("; ", $va_display_flag_buf);
                }
            }
            $vs_label = '';
            $vb_dont_use_labels_for_ca_objects = (bool) $t_item->getAppConfig()->get('ca_objects_dont_use_labels');
            if (!($vs_table_name === 'ca_objects' && $vb_dont_use_labels_for_ca_objects)) {
                if ($vs_get_spec = $po_view->request->config->get("{$vs_table_name}_inspector_display_title")) {
                    $vs_label = caProcessTemplateForIDs($vs_get_spec, $vs_table_name, array($t_item->getPrimaryKey()));
                } else {
                    $va_object_collection_collection_ancestors = $po_view->getVar('object_collection_collection_ancestors');
                    if ($t_item->tableName() == 'ca_objects' && $t_item->getAppConfig()->get('ca_objects_x_collections_hierarchy_enabled') && is_array($va_object_collection_collection_ancestors) && sizeof($va_object_collection_collection_ancestors)) {
                        $va_collection_links = array();
                        foreach ($va_object_collection_collection_ancestors as $va_collection_ancestor) {
                            $va_collection_links[] = caEditorLink($po_view->request, $va_collection_ancestor['label'], '', 'ca_collections', $va_collection_ancestor['collection_id']);
                        }
                        $vs_label .= join(" / ", $va_collection_links) . ' &gt; ';
                    }
                    if (method_exists($t_item, 'getLabelForDisplay')) {
                        $vn_parent_index = sizeof($va_ancestors) - 1;
                        if ($vn_parent_id && ($vs_table_name != 'ca_places' || $vn_parent_index > 0)) {
                            $va_parent = $va_ancestors[$vn_parent_index];
                            $vs_disp_fld = $t_item->getLabelDisplayField();
                            if ($va_parent['NODE'][$vs_disp_fld] && ($vs_editor_link = caEditorLink($po_view->request, $va_parent['NODE'][$vs_disp_fld], '', $vs_table_name, $va_parent['NODE'][$t_item->primaryKey()]))) {
                                $vs_label .= $vs_editor_link . ' &gt; ' . $t_item->getLabelForDisplay();
                            } else {
                                $vs_label .= ($va_parent['NODE'][$vs_disp_fld] ? $va_parent['NODE'][$vs_disp_fld] . ' &gt; ' : '') . $t_item->getLabelForDisplay();
                            }
                        } else {
                            $vs_label .= $t_item->getLabelForDisplay();
                            if ($vs_table_name === 'ca_editor_uis' && in_array($po_view->request->getAction(), array('EditScreen', 'DeleteScreen', 'SaveScreen'))) {
                                $t_screen = new ca_editor_ui_screens($po_view->request->getParameter('screen_id', pInteger));
                                if (!($vs_screen_name = $t_screen->getLabelForDisplay())) {
                                    $vs_screen_name = _t('new screen');
                                }
                                $vs_label .= " &gt; " . $vs_screen_name;
                            }
                        }
                    } else {
                        $vs_label .= $t_item->get('name');
                    }
                }
            }
            $vb_show_idno = (bool) ($vs_idno = $t_item->get($t_item->getProperty('ID_NUMBERING_ID_FIELD')));
            if (!$vs_label) {
                switch ($vs_table_name) {
                    case 'ca_commerce_orders':
                        if ($t_item->get('order_type') == 'L') {
                            if ($vs_org = $t_item->get('billing_organization')) {
                                $vs_label = _t('%5 #%4 on %1 to %2 (%3)', caGetLocalizedDate($t_item->get('created_on', array('getDirectDate' => true)), array('dateFormat' => 'delimited', 'timeOmit' => true)), $t_item->get('billing_fname') . ' ' . $t_item->get('billing_lname'), $vs_org, $t_item->getOrderNumber(), caUcFirstUTF8Safe($t_item->getProperty('NAME_SINGULAR')));
                            } else {
                                $vs_label = _t('%4 #%3 on %1 to %2', caGetLocalizedDate($t_item->get('created_on', array('getDirectDate' => true)), array('dateFormat' => 'delimited', 'timeOmit' => true)), $t_item->get('billing_fname') . ' ' . $t_item->get('billing_lname'), $t_item->getOrderNumber(), caUcFirstUTF8Safe($t_item->getProperty('NAME_SINGULAR')));
                            }
                        } else {
                            if ($vs_org = $t_item->get('billing_organization')) {
                                $vs_label = _t('%5 #%4 on %1 from %2 (%3)', caGetLocalizedDate($t_item->get('created_on', array('getDirectDate' => true)), array('dateFormat' => 'delimited', 'timeOmit' => true)), $t_item->get('billing_fname') . ' ' . $t_item->get('billing_lname'), $vs_org, $t_item->getOrderNumber(), caUcFirstUTF8Safe($t_item->getProperty('NAME_SINGULAR')));
                            } else {
                                $vs_label = _t('%4 #%3 on %1 from %2', caGetLocalizedDate($t_item->get('created_on', array('getDirectDate' => true)), array('dateFormat' => 'delimited', 'timeOmit' => true)), $t_item->get('billing_fname') . ' ' . $t_item->get('billing_lname'), $t_item->getOrderNumber(), caUcFirstUTF8Safe($t_item->getProperty('NAME_SINGULAR')));
                            }
                        }
                        break;
                    default:
                        if ($vs_table_name === 'ca_objects' && $vb_dont_use_labels_for_ca_objects) {
                            $vs_label = $vs_idno;
                            $vb_show_idno = false;
                        } else {
                            $vs_label = '[' . _t('BLANK') . ']';
                        }
                        break;
                }
            }
            $vs_buf .= "<div class='recordTitle {$vs_table_name}' style='width:190px; overflow:hidden;'>{$vs_label}" . ($vb_show_idno ? "<a title='{$vs_idno}'>" . ($vs_idno ? " ({$vs_idno})" : '') : "") . "</a></div>";
            if ($vs_table_name === 'ca_object_lots' && $t_item->getPrimaryKey()) {
                $vs_buf .= "<div id='inspectorLotMediaDownload'><strong>" . (($vn_num_objects = $t_item->numObjects()) == 1 ? _t('Lot contains %1 object', $vn_num_objects) : _t('Lot contains %1 objects', $vn_num_objects)) . "</strong>\n";
            }
            if ($po_view->request->config->get("include_custom_inspector")) {
                if (file_exists($po_view->request->getViewsDirectoryPath() . "/bundles/inspector_info.php")) {
                    $vo_inspector_view = new View($po_view->request, $po_view->request->getViewsDirectoryPath() . "/bundles/");
                    $vo_inspector_view->setVar('t_item', $t_item);
                    $vs_buf .= $vo_inspector_view->render('inspector_info.php');
                }
            }
        } else {
            $vs_parent_name = '';
            if ($vn_parent_id = $po_view->request->getParameter('parent_id', pInteger)) {
                $t_parent = clone $t_item;
                $t_parent->load($vn_parent_id);
                $vs_parent_name = $t_parent->getLabelForDisplay();
            }
            $vs_buf .= "<div class='creatingNew'>" . _t("Creating new %1", $vs_type_name) . " " . ($vs_parent_name ? _t("%1 &gt; New %2", $vs_parent_name, $vs_type_name) : '') . "</div>\n";
            $vs_buf .= "<br/>\n";
        }
        // -------------------------------------------------------------------------------------
        if ($t_item->getPrimaryKey()) {
            if (sizeof($va_reps) > 0) {
                $va_imgs = array();
                $vs_buf .= "<div id='inspectorMedia'>";
                $vn_r = $vn_primary_index = 0;
                foreach ($va_reps as $va_rep) {
                    if (!($va_rep['info']['preview170']['WIDTH'] && $va_rep['info']['preview170']['HEIGHT'])) {
                        continue;
                    }
                    if ($vb_is_primary = isset($va_rep['is_primary']) && (bool) $va_rep['is_primary']) {
                        $vn_primary_index = $vn_r;
                    }
                    $va_imgs[] = "{url:'" . $va_rep['urls']['preview170'] . "', width: " . $va_rep['info']['preview170']['WIDTH'] . ", height: " . $va_rep['info']['preview170']['HEIGHT'] . ", link: '#', onclick:  'caMediaPanel.showPanel(\\'" . caNavUrl($po_view->request, '*', '*', 'GetMediaOverlay', array($t_item->primaryKey() => $vn_item_id, 'representation_id' => $va_rep['representation_id'])) . "\\')'}";
                    $vn_r++;
                }
                if (sizeof($va_reps) > 1) {
                    $vs_buf .= "\n\t\t\t\t\t<div class='leftScroll'>\n\t\t\t\t\t\t<a href='#' onclick='inspectorInfoRepScroller.scrollToPreviousImage(); return false;'>" . caNavIcon($po_view->request, __CA_NAV_BUTTON_SCROLL_LT__) . "</a>\n\t\t\t\t\t</div>\n\t\t";
                }
                if (sizeof($va_imgs) > 0) {
                    $vs_buf .= "\n\t\t\t\t<div id='inspectorInfoRepScrollingViewer' style='position: relative;'>\n\t\t\t\t\t<div id='inspectorInfoRepScrollingViewerContainer'>\n\t\t\t\t\t\t<div id='inspectorInfoRepScrollingViewerImageContainer'></div>\n\t\t\t\t\t</div>\n\t\t\t\t</div>\n\t\t";
                    if (sizeof($va_reps) > 1) {
                        $vs_buf .= "\n\t\t\t\t\t<div class='rightScroll'>\n\t\t\t\t\t\t<a href='#' onclick='inspectorInfoRepScroller.scrollToNextImage(); return false;'>" . caNavIcon($po_view->request, __CA_NAV_BUTTON_SCROLL_RT__) . "</a>\n\t\t\t\t\t</div>\n\t\t";
                    }
                    TooltipManager::add(".leftScroll", _t('Previous'));
                    TooltipManager::add(".rightScroll", _t('Next'));
                    $vs_buf .= "<script type='text/javascript'>";
                    $vs_buf .= "\n\t\t\t\t\tvar inspectorInfoRepScroller = caUI.initImageScroller([" . join(",", $va_imgs) . "], 'inspectorInfoRepScrollingViewerImageContainer', {\n\t\t\t\t\t\t\tcontainerWidth: 170, containerHeight: 170,\n\t\t\t\t\t\t\timageCounterID: 'inspectorInfoRepScrollingViewerCounter',\n\t\t\t\t\t\t\tscrollingImageClass: 'inspectorInfoRepScrollerImage',\n\t\t\t\t\t\t\tscrollingImagePrefixID: 'inspectorInfoRep',\n\t\t\t\t\t\t\tinitialIndex: {$vn_primary_index}\n\t\t\t\t\t\t\t\n\t\t\t\t\t});\n\t\t\t\t</script>";
                }
                $vs_buf .= "</div>\n";
                if ($vs_get_spec = $po_view->request->config->get("{$vs_table_name}_inspector_display_below_media")) {
                    $vs_buf .= caProcessTemplateForIDs($vs_get_spec, $vs_table_name, array($t_item->getPrimaryKey()));
                }
            }
            $vs_buf .= "<div id='toolIcons'>";
            if ($vn_item_id) {
                # --- watch this link
                $vs_watch = "";
                if (in_array($vs_table_name, array('ca_objects', 'ca_object_lots', 'ca_entities', 'ca_places', 'ca_occurrences', 'ca_collections', 'ca_storage_locations'))) {
                    require_once __CA_MODELS_DIR__ . '/ca_watch_list.php';
                    $t_watch_list = new ca_watch_list();
                    $vs_watch = "<div class='watchThis'><a href='#' title='" . _t('Add/remove item to/from watch list.') . "' onclick='caToggleItemWatch(); return false;' id='caWatchItemButton'>" . caNavIcon($po_view->request, $t_watch_list->isItemWatched($vn_item_id, $t_item->tableNum(), $po_view->request->user->get("user_id")) ? __CA_NAV_BUTTON_UNWATCH__ : __CA_NAV_BUTTON_WATCH__) . "</a></div>";
                    $vs_buf .= "\n<script type='text/javascript'>\n\t\tfunction caToggleItemWatch() {\n\t\t\tvar url = '" . caNavUrl($po_view->request, $po_view->request->getModulePath(), $po_view->request->getController(), 'toggleWatch', array($t_item->primaryKey() => $vn_item_id)) . "';\n\t\t\t\n\t\t\tjQuery.getJSON(url, {}, function(data, status) {\n\t\t\t\tif (data['status'] == 'ok') {\n\t\t\t\t\tjQuery('#caWatchItemButton').html((data['state'] == 'watched') ? '" . addslashes(caNavIcon($po_view->request, __CA_NAV_BUTTON_UNWATCH__)) . "' : '" . addslashes(caNavIcon($po_view->request, __CA_NAV_BUTTON_WATCH__)) . "');\n\t\t\t\t} else {\n\t\t\t\t\tconsole.log('Error toggling watch status for item: ' + data['errors']);\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\t\t</script>\n";
                }
                $vs_buf .= "{$vs_watch}\n";
                TooltipManager::add("#caWatchItemButton", _t('Watch/Unwatch this record'));
                if ($po_view->request->user->canDoAction("can_change_type_{$vs_table_name}")) {
                    $vs_buf .= "<div id='inspectorChangeType'><div id='inspectorChangeTypeButton'><a href='#' onclick='caTypeChangePanel.showPanel(); return false;'>" . caNavIcon($po_view->request, __CA_NAV_BUTTON_CHANGE__ . " Change Type", array('title' => _t('Change type'))) . "</a></div></div>\n";
                    $vo_change_type_view = new View($po_view->request, $po_view->request->getViewsDirectoryPath() . "/bundles/");
                    $vo_change_type_view->setVar('t_item', $t_item);
                    FooterManager::add($vo_change_type_view->render("change_type_html.php"));
                    TooltipManager::add("#inspectorChangeType", _t('Change Record Type'));
                }
                if ($t_item->getPrimaryKey() && $po_view->request->config->get($vs_table_name . '_show_add_child_control_in_inspector')) {
                    $vb_show_add_child_control = true;
                    if (is_array($va_restrict_add_child_control_to_types = $po_view->request->config->getList($vs_table_name . '_restrict_child_control_in_inspector_to_types')) && sizeof($va_restrict_add_child_control_to_types)) {
                        $t_type_instance = $t_item->getTypeInstance();
                        if (!in_array($t_type_instance->get('idno'), $va_restrict_add_child_control_to_types) && !in_array($t_type_instance->getPrimaryKey(), $va_restrict_add_child_control_to_types)) {
                            $vb_show_add_child_control = false;
                        }
                    }
                    if ($vb_show_add_child_control) {
                        if ((bool) $po_view->request->config->get($vs_table_name . '_enforce_strict_type_hierarchy')) {
                            // strict menu
                            $vs_type_list = $t_item->getTypeListAsHTMLFormElement('type_id', array('style' => 'width: 90px; font-size: 9px;'), array('childrenOfCurrentTypeOnly' => true, 'directChildrenOnly' => $po_view->request->config->get($vs_table_name . '_enforce_strict_type_hierarchy') == '~' ? false : true, 'returnHierarchyLevels' => true, 'access' => __CA_BUNDLE_ACCESS_EDIT__));
                        } else {
                            // all types
                            $vs_type_list = $t_item->getTypeListAsHTMLFormElement('type_id', array('style' => 'width: 90px; font-size: 9px;'), array('access' => __CA_BUNDLE_ACCESS_EDIT__));
                        }
                        if ($vs_type_list) {
                            $vs_buf .= "<div id='inspectorCreateChild'><div id='inspectorCreateChildButton'><a href='#' onclick='caCreateChildPanel.showPanel(); return false;'>" . caNavIcon($po_view->request, __CA_NAV_BUTTON_CHILD__, array('title' => _t('Create Child Record'))) . "</a></div></div>\n";
                            $vo_create_child_view = new View($po_view->request, $po_view->request->getViewsDirectoryPath() . "/bundles/");
                            $vo_create_child_view->setVar('t_item', $t_item);
                            $vo_create_child_view->setVar('type_list', $vs_type_list);
                            FooterManager::add($vo_create_child_view->render("create_child_html.php"));
                            TooltipManager::add("#inspectorCreateChildButton", _t('Create a child record under this one'));
                        }
                    }
                }
            }
            if ($po_view->request->user->canDoAction('can_duplicate_' . $vs_table_name) && $t_item->getPrimaryKey()) {
                $vs_buf .= '<div id="caDuplicateItemButton">';
                $vs_buf .= caFormTag($po_view->request, 'Edit', 'DuplicateItemForm', $po_view->request->getModulePath() . '/' . $po_view->request->getController(), 'post', 'multipart/form-data', '_top', array('disableUnsavedChangesWarning' => true, 'noTimestamp' => true));
                $vs_buf .= caFormSubmitLink($po_view->request, caNavIcon($po_view->request, __CA_NAV_BUTTON_DUPLICATE__), '', 'DuplicateItemForm');
                $vs_buf .= caHTMLHiddenInput($t_item->primaryKey(), array('value' => $t_item->getPrimaryKey()));
                $vs_buf .= caHTMLHiddenInput('mode', array('value' => 'dupe'));
                $vs_buf .= "</form>";
                $vs_buf .= "</div>";
                TooltipManager::add("#caDuplicateItemButton", _t('Duplicate this %1', mb_strtolower($vs_type_name, 'UTF-8')));
            }
            //
            // Download media in lot ($vn_num_objects is only set for object lots)
            if ($vn_num_objects > 0) {
                $vs_buf .= "<div id='inspectorLotMediaDownloadButton'>" . caNavLink($po_view->request, caNavIcon($po_view->request, __CA_NAV_BUTTON_DOWNLOAD__), "button", $po_view->request->getModulePath(), $po_view->request->getController(), 'getLotMedia', array('lot_id' => $t_item->getPrimaryKey(), 'download' => 1), array()) . "</div>\n";
                TooltipManager::add('#inspectorLotMediaDownloadButton', _t("Download all media associated with objects in this lot"));
            }
            //
            // Download media in set
            if ($vs_table_name == 'ca_sets' && sizeof($t_item->getItemRowIDs()) > 0) {
                $vs_buf .= "<div id='inspectorSetMediaDownloadButton'>" . caNavLink($po_view->request, caNavIcon($po_view->request, __CA_NAV_BUTTON_DOWNLOAD__), "button", $po_view->request->getModulePath(), $po_view->request->getController(), 'getSetMedia', array('set_id' => $t_item->getPrimaryKey(), 'download' => 1), array()) . "</div>\n";
                TooltipManager::add('#inspectorSetMediaDownloadButton', _t("Download all media associated with records in this set"));
            }
            $vs_more_info = '';
            // list of sets in which item is a member
            $t_set = new ca_sets();
            if (is_array($va_sets = caExtractValuesByUserLocale($t_set->getSetsForItem($t_item->tableNum(), $t_item->getPrimaryKey(), array('user_id' => $po_view->request->getUserID(), 'access' => __CA_SET_READ_ACCESS__)))) && sizeof($va_sets)) {
                $va_links = array();
                foreach ($va_sets as $vn_set_id => $va_set) {
                    $va_links[] = "<a href='" . caEditorUrl($po_view->request, 'ca_sets', $vn_set_id) . "'>" . $va_set['name'] . "</a>";
                }
                $vs_more_info .= "<div><strong>" . (sizeof($va_links) == 1 ? _t("In set") : _t("In sets")) . "</strong> " . join(", ", $va_links) . "</div>\n";
            }
            // export options
            if ($vn_item_id && ($vs_select = $po_view->getVar('available_mappings_as_html_select'))) {
                $vs_more_info .= "<div class='inspectorExportControls'>" . caFormTag($po_view->request, 'exportItem', 'caExportForm', null, 'post', 'multipart/form-data', '_top', array('disableUnsavedChangesWarning' => true));
                $vs_more_info .= $vs_select;
                $vs_more_info .= caHTMLHiddenInput($t_item->primaryKey(), array('value' => $t_item->getPrimaryKey()));
                $vs_more_info .= caHTMLHiddenInput('download', array('value' => 1));
                $vs_more_info .= caFormSubmitLink($po_view->request, 'Export &rsaquo;', 'button', 'caExportForm');
                $vs_more_info .= "</form></div>";
            }
            $va_creation = $t_item->getCreationTimestamp();
            $va_last_change = $t_item->getLastChangeTimestamp();
            if ($va_creation['timestamp'] || $va_last_change['timestamp']) {
                $vs_more_info .= "<div class='inspectorChangeDateList'>";
                if ($va_creation['timestamp']) {
                    if (!trim($vs_name = $va_creation['fname'] . ' ' . $va_creation['lname'])) {
                        $vs_name = null;
                    }
                    $vs_interval = ($vn_t = time() - $va_creation['timestamp']) == 0 ? _t('Just now') : _t('%1 ago', caFormatInterval($vn_t, 2));
                    $vs_more_info .= "<div class='inspectorChangeDateListLine'  id='caInspectorCreationDate'>" . ($vs_name ? _t('<strong>Created</strong><br/>%1 by %2', $vs_interval, $vs_name) : _t('<strong>Created</strong><br/>%1', $vs_interval)) . "</div>";
                    TooltipManager::add("#caInspectorCreationDate", "<h2>" . _t('Created on') . "</h2>" . _t('Created on %1', caGetLocalizedDate($va_creation['timestamp'], array('dateFormat' => 'delimited'))));
                }
                if ($va_last_change['timestamp'] && $va_creation['timestamp'] != $va_last_change['timestamp']) {
                    if (!trim($vs_name = $va_last_change['fname'] . ' ' . $va_last_change['lname'])) {
                        $vs_name = null;
                    }
                    $vs_interval = ($vn_t = time() - $va_last_change['timestamp']) == 0 ? _t('Just now') : _t('%1 ago', caFormatInterval($vn_t, 2));
                    $vs_more_info .= "<div class='inspectorChangeDateListLine' id='caInspectorChangeDate'>" . ($vs_name ? _t('<strong>Last changed</strong><br/>%1 by %2', $vs_interval, $vs_name) : _t('<strong>Last changed</strong><br/>%1', $vs_interval)) . "</div>";
                    TooltipManager::add("#caInspectorChangeDate", "<h2>" . _t('Last changed on') . "</h2>" . _t('Last changed on %1', caGetLocalizedDate($va_last_change['timestamp'], array('dateFormat' => 'delimited'))));
                }
                if (method_exists($t_item, 'getMetadataDictionaryRuleViolations') && is_array($va_violations = $t_item->getMetadataDictionaryRuleViolations()) && ($vn_num_violations = sizeof($va_violations)) > 0) {
                    $va_violation_messages = array();
                    foreach ($va_violations as $vn_violation_id => $va_violation) {
                        $vs_label = $t_item->getDisplayLabel($va_violation['bundle_name']);
                        $va_violation_messages[] = "<li><em><u>{$vs_label}</u></em> " . $va_violation['violationMessage'] . "</li>";
                    }
                    $vs_more_info .= "<div id='caInspectorViolationsList'>" . ($vs_num_violations_display = "<img src='" . $po_view->request->getThemeUrlPath() . "/graphics/icons/warning_small.gif' border='0'/> " . ($vn_num_violations > 1 ? _t('%1 problems require attention', $vn_num_violations) : _t('%1 problem requires attention', $vn_num_violations))) . "</div>\n";
                    TooltipManager::add("#caInspectorViolationsList", "<h2>{$vs_num_violations_display}</h2><ol>" . join("\n", $va_violation_messages)) . "</ol>\n";
                }
                $vs_more_info .= "</div>\n";
            }
            if ($vs_get_spec = $po_view->request->config->get("{$vs_table_name}_inspector_display_more_info")) {
                $vs_more_info .= caProcessTemplateForIDs($vs_get_spec, $vs_table_name, array($t_item->getPrimaryKey()));
            }
            if ($vs_more_info) {
                $vs_buf .= "<div class='button info'><a href='#' id='inspectorMoreInfo'>" . caNavIcon($po_view->request, __CA_NAV_BUTTON_INFO2__) . "</a></div>\n\t\t\t<div id='inspectorInfo' >";
                $vs_buf .= $vs_more_info . "</div>\n";
                TooltipManager::add("#inspectorMoreInfo", _t('See more information about this record'));
            }
            $vs_buf .= "</div><!--End tooIcons-->";
        }
        // -------------------------------------------------------------------------------------
        //
        // Item-specific information
        //
        //
        // Output info for related items
        //
        if (!$t_item->getPrimaryKey()) {
            // only applies to new records
            $vs_rel_table = $po_view->request->getParameter('rel_table', pString);
            $vn_rel_type_id = $po_view->request->getParameter('rel_type_id', pString);
            $vn_rel_id = $po_view->request->getParameter('rel_id', pInteger);
            if ($vs_rel_table && $po_view->request->datamodel->tableExists($vs_rel_table) && $vn_rel_type_id && $vn_rel_id) {
                $t_rel = $po_view->request->datamodel->getTableInstance($vs_rel_table);
                if ($t_rel && $t_rel->load($vn_rel_id)) {
                    $vs_buf .= '<strong>' . _t("Will be related to %1", $t_rel->getTypeName()) . '</strong>: ' . $t_rel->getLabelForDisplay();
                }
            }
        }
        //
        // Output lot info for ca_objects
        //
        $vb_is_currently_part_of_lot = true;
        if (!($vn_lot_id = $t_item->get('lot_id'))) {
            $vn_lot_id = $po_view->request->getParameter('lot_id', pInteger);
            $vb_is_currently_part_of_lot = false;
        }
        if ($vs_table_name === 'ca_objects' && $vn_lot_id) {
            require_once __CA_MODELS_DIR__ . '/ca_object_lots.php';
            $va_lot_lots = caGetTypeListForUser('ca_object_lots', array('access' => __CA_BUNDLE_ACCESS_READONLY__));
            $t_lot = new ca_object_lots($vn_lot_id);
            if ($t_lot->get('deleted') == 0 && in_array($t_lot->get('type_id'), $va_lot_lots)) {
                if (!($vs_lot_displayname = $t_lot->get('idno_stub'))) {
                    if (!($vs_lot_displayname = $t_lot->getLabelForDisplay())) {
                        $vs_lot_displayname = "Lot {$vn_lot_id}";
                    }
                }
                if ($vs_lot_displayname) {
                    if (!($vs_part_of_lot_msg = $po_view->request->config->get("ca_objects_inspector_part_of_lot_msg"))) {
                        $vs_part_of_lot_msg = _t('Part of lot');
                    }
                    if (!($vs_will_be_part_of_lot_msg = $po_view->request->config->get("ca_objects_inspector_will_be_part_of_lot_msg"))) {
                        $vs_will_be_part_of_lot_msg = _t('Will be part of lot');
                    }
                    $vs_buf .= "<strong>" . ($vb_is_currently_part_of_lot ? $vs_part_of_lot_msg : $vs_will_be_part_of_lot_msg) . "</strong>: " . caNavLink($po_view->request, $vs_lot_displayname, '', 'editor/object_lots', 'ObjectLotEditor', 'Edit', array('lot_id' => $vn_lot_id));
                }
            }
        }
        $va_object_container_types = $po_view->request->config->getList('ca_objects_container_types');
        $va_object_component_types = $po_view->request->config->getList('ca_objects_component_types');
        $vb_can_add_component = $vs_table_name === 'ca_objects' && $t_item->getPrimaryKey() && $po_view->request->user->canDoAction('can_create_ca_objects') && $t_item->canTakeComponents();
        if (method_exists($t_item, 'getComponentCount')) {
            if ($vn_component_count = $t_item->getComponentCount()) {
                if ($t_ui && ($vs_component_list_screen = $t_ui->getScreenWithBundle("ca_objects_components_list", $po_view->request)) && $vs_component_list_screen !== $po_view->request->getActionExtra()) {
                    $vs_component_count_link = caNavLink($po_view->request, $vn_component_count == 1 ? _t('%1 component', $vn_component_count) : _t('%1 components', $vn_component_count), '', '*', '*', $po_view->request->getAction() . '/' . $vs_component_list_screen, array($t_item->primaryKey() => $t_item->getPrimaryKey()));
                } else {
                    $vs_component_count_link = $vn_component_count == 1 ? _t('%1 component', $vn_component_count) : _t('%1 components', $vn_component_count);
                }
                $vs_buf .= "<br/><strong>" . _t('Has') . ":</strong> {$vs_component_count_link}";
            }
        }
        if ($vb_can_add_component) {
            $vs_buf .= ' <a href="#" onclick=\'caObjectComponentPanel.showPanel("' . caNavUrl($po_view->request, '*', 'ObjectComponent', 'Form', array('parent_id' => $t_item->getPrimaryKey())) . '"); return false;\')>' . caNavIcon($po_view->request, __CA_NAV_BUTTON_ADD__) . '</a>';
            $vo_change_type_view = new View($po_view->request, $po_view->request->getViewsDirectoryPath() . "/bundles/");
            $vo_change_type_view->setVar('t_item', $t_item);
            FooterManager::add($vo_change_type_view->render("create_component_html.php"));
        }
        //
        // Output lot info for ca_object_lots
        //
        if ($vs_table_name === 'ca_object_lots' && $t_item->getPrimaryKey()) {
            $va_component_types = $po_view->request->config->getList('ca_objects_component_types');
            if (is_array($va_component_types) && sizeof($va_component_types)) {
                $vs_buf .= "<strong>" . (($vn_num_objects = $t_item->numObjects(null, array('return' => 'objects'))) == 1 ? _t('Lot contains %1 object', $vn_num_objects) : _t('Lot contains %1 objects', $vn_num_objects)) . "</strong>\n";
                $vs_buf .= "<strong>" . (($vn_num_components = $t_item->numObjects(null, array('return' => 'components'))) == 1 ? _t('Lot contains %1 component', $vn_num_components) : _t('Lot contains %1 components', $vn_num_components)) . "</strong>\n";
            } else {
                $vs_buf .= "<strong>" . (($vn_num_objects = $t_item->numObjects()) == 1 ? _t('Lot contains %1 object', $vn_num_objects) : _t('Lot contains %1 objects', $vn_num_objects)) . "</strong>\n";
            }
            if ((bool) $po_view->request->config->get('allow_automated_renumbering_of_objects_in_a_lot') && ($va_nonconforming_objects = $t_item->getObjectsWithNonConformingIdnos())) {
                $vs_buf .= '<br/><br/><em>' . (($vn_c = sizeof($va_nonconforming_objects)) == 1 ? _t('There is %1 object with non-conforming numbering', $vn_c) : _t('There are %1 objects with non-conforming numbering', $vn_c)) . "</em>\n";
                $vs_buf .= "<a href='#' onclick='jQuery(\"#inspectorNonConformingNumberList\").toggle(250); return false;'>" . caNavIcon($po_view->request, __CA_NAV_BUTTON_ADD__);
                $vs_buf .= "<div id='inspectorNonConformingNumberList' class='inspectorNonConformingNumberList'><div class='inspectorNonConformingNumberListScroll'><ol>\n";
                foreach ($va_nonconforming_objects as $vn_object_id => $va_object_info) {
                    $vs_buf .= '<li>' . caEditorLink($po_view->request, $va_object_info['idno'], '', 'ca_objects', $vn_object_id) . "</li>\n";
                }
                $vs_buf .= "</ol></div>";
                $vs_buf .= caNavLink($po_view->request, _t('Re-number objects') . ' &rsaquo;', 'button', $po_view->request->getModulePath(), $po_view->request->getController(), 'renumberObjects', array('lot_id' => $t_item->getPrimaryKey()));
                $vs_buf .= "</div>\n";
            }
            require_once __CA_MODELS_DIR__ . '/ca_objects.php';
            $t_object = new ca_objects();
            $vs_buf .= "<div class='inspectorLotObjectTypeControls'><form action='#' id='caAddObjectToLotForm'>";
            if ((bool) $po_view->request->config->get('ca_objects_enforce_strict_type_hierarchy')) {
                // strict menu
                $vs_buf .= _t('Add new %1 to lot', $t_object->getTypeListAsHTMLFormElement('type_id', array('id' => 'caAddObjectToLotForm_type_id'), array('childrenOfCurrentTypeOnly' => true, 'directChildrenOnly' => $po_view->request->config->get('ca_objects_enforce_strict_type_hierarchy') == '~' ? false : true, 'returnHierarchyLevels' => true, 'access' => __CA_BUNDLE_ACCESS_EDIT__)));
            } else {
                // all types
                $vs_buf .= _t('Add new %1 to lot', $t_object->getTypeListAsHTMLFormElement('type_id', array('id' => 'caAddObjectToLotForm_type_id'), array('access' => __CA_BUNDLE_ACCESS_EDIT__)));
            }
            $vs_buf .= " <a href='#' onclick='caAddObjectToLotForm()'>" . caNavIcon($po_view->request, __CA_NAV_BUTTON_ADD__) . '</a>';
            $vs_buf .= "</form></div>\n";
            $vs_buf .= "<script type='text/javascript'>\n\tfunction caAddObjectToLotForm() { \n\t\twindow.location='" . caEditorUrl($po_view->request, 'ca_objects', 0, false, array('lot_id' => $t_item->getPrimaryKey(), 'rel' => 1, 'type_id' => '')) . "' + jQuery('#caAddObjectToLotForm_type_id').val();\n\t}\n\tjQuery(document).ready(function() {\n\t\tjQuery('#objectLotsNonConformingNumberList').hide();\n\t});\n</script>\n";
        }
        if ($vs_table_name === 'ca_objects') {
            //
            // Output loan info for ca_objects
            //
            if ($po_view->request->user->canDoAction('can_manage_clients') && ($va_loan_details = $t_item->isOnLoan())) {
                $vs_buf .= "<div>" . caNavLink($po_view->request, _t('On loan to %1', $va_loan_details['billing_fname'] . ' ' . $va_loan_details['billing_lname']), 'inspectorOnLoan', 'client/library', 'OrderEditor', 'Edit', array('order_id' => $va_loan_details['order_id'])) . "</div>";
            }
            //
            // Output checkout info for ca_objects
            //
            if ((bool) $po_view->request->config->get('enable_client_services') && ((bool) $po_view->request->config->get('enable_client_services_sales') || (bool) $po_view->request->config->get('enable_client_services_library')) && $t_item->canBeCheckedOut() && ($va_checkout_status = $t_item->getCheckoutStatus(array('returnAsArray' => true)))) {
                $vs_buf .= "<div class='inspectorCheckedOut'>" . $va_checkout_status['status_display'];
                if ($va_checkout_status['user_name']) {
                    $vs_buf .= _t("; checked out by %1", $va_checkout_status['user_name']);
                }
                $vs_buf .= "</div>";
            }
        }
        //
        // Output related objects for ca_object_representations
        //
        if ($vs_table_name === 'ca_object_representations') {
            foreach (array('ca_objects', 'ca_object_lots', 'ca_entities', 'ca_places', 'ca_occurrences', 'ca_collections', 'ca_storage_locations', 'ca_loans', 'ca_movements') as $vs_rel_table) {
                if (sizeof($va_objects = $t_item->getRelatedItems($vs_rel_table))) {
                    $vs_buf .= "<div><strong>" . _t("Related %1", $o_dm->getTableProperty($vs_rel_table, 'NAME_PLURAL')) . "</strong>: <br/>\n";
                    $vs_screen = '';
                    if ($t_ui = ca_editor_uis::loadDefaultUI($vs_rel_table, $po_view->request, null)) {
                        $vs_screen = $t_ui->getScreenWithBundle('ca_object_representations', $po_view->request);
                    }
                    foreach ($va_objects as $vn_rel_id => $va_rel_info) {
                        if ($vs_label = array_shift($va_rel_info['labels'])) {
                            $vs_buf .= caEditorLink($po_view->request, '&larr; ' . $vs_label . ' (' . $va_rel_info['idno'] . ')', '', $vs_rel_table, $va_rel_info[$o_dm->getTablePrimaryKeyName($vs_rel_table)], array(), array(), array('action' => 'Edit' . ($vs_screen ? "/{$vs_screen}" : ""))) . "<br/>\n";
                        }
                    }
                    $vs_buf .= "</div>\n";
                }
            }
        }
        //
        // Output related object reprsentation for ca_representation_annotation
        //
        if ($vs_table_name === 'ca_representation_annotations') {
            if ($vn_representation_id = $t_item->get('representation_id')) {
                $vs_buf .= "<div><strong>" . _t("Applied to representation") . "</strong>: <br/>\n";
                $t_rep = new ca_object_representations($vn_representation_id);
                $vs_buf .= caNavLink($po_view->request, '&larr; ' . $t_rep->getLabelForDisplay(), '', 'editor/object_representations', 'ObjectRepresentationEditor', 'Edit/' . $po_view->getVar('representation_editor_screen'), array('representation_id' => $vn_representation_id)) . '<br/>';
                $vs_buf .= "</div>\n";
            }
        }
        //
        // Output extra useful info for sets
        //
        if ($vs_table_name === 'ca_sets') {
            $vn_set_item_count = $t_item->getItemCount(array('user_id' => $po_view->request->getUserID()));
            if ($vn_set_item_count > 0 && $po_view->request->user->canDoAction('can_batch_edit_' . $o_dm->getTableName($t_item->get('table_num')))) {
                $vs_buf .= caNavButton($po_view->request, __CA_NAV_BUTTON_BATCH_EDIT__, _t('Batch edit'), 'editorBatchSetEditorLink', 'batch', 'Editor', 'Edit', array('set_id' => $t_item->getPrimaryKey()), array(), array('icon_position' => __CA_NAV_BUTTON_ICON_POS_LEFT__, 'no_background' => true, 'dont_show_content' => true));
            }
            $vs_buf .= "<div><strong>" . _t("Number of items") . "</strong>: {$vn_set_item_count}<br/>\n";
            if ($t_item->getPrimaryKey()) {
                $vn_set_table_num = $t_item->get('table_num');
                $vs_set_table_name = $o_dm->getTableName($vn_set_table_num);
                $vs_buf .= "<strong>" . _t("Type of content") . "</strong>: " . caGetTableDisplayName($vn_set_table_num) . "<br/>\n";
                $vs_buf .= "</div>\n";
            } else {
                if ($vn_set_table_num = $po_view->request->getParameter('table_num', pInteger)) {
                    $vs_buf .= "<div><strong>" . _t("Type of content") . "</strong>: " . caGetTableDisplayName($vn_set_table_num) . "<br/>\n";
                    $vs_buf .= "</div>\n";
                }
            }
            $t_user = new ca_users(($vn_user_id = $t_item->get('user_id')) ? $vn_user_id : $po_view->request->getUserID());
            if ($t_user->getPrimaryKey()) {
                $vs_buf .= "<div><strong>" . _t('Owner') . "</strong>: " . $t_user->get('fname') . ' ' . $t_user->get('lname') . "</div>\n";
            }
            if ($po_view->request->user->canDoAction('can_export_' . $vs_set_table_name) && $t_item->getPrimaryKey() && sizeof(ca_data_exporters::getExporters($vn_set_table_num)) > 0) {
                $vs_buf .= '<div style="border-top: 1px solid #aaaaaa; margin-top: 5px; font-size: 10px; text-align: right;" id="caExportItemButton">';
                $vs_buf .= _t('Export this set of records') . "&nbsp; ";
                $vs_buf .= "<a class='button' onclick='jQuery(\"#exporterFormList\").show();' style='text-align:right;' href='#'>" . caNavIcon($po_view->request, __CA_NAV_BUTTON_ADD__) . "</a>";
                $vs_buf .= caFormTag($po_view->request, 'ExportData', 'caExportForm', 'manage/MetadataExport', 'post', 'multipart/form-data', '_top', array('disableUnsavedChangesWarning' => true));
                $vs_buf .= "<div id='exporterFormList'>";
                $vs_buf .= ca_data_exporters::getExporterListAsHTMLFormElement('exporter_id', $vn_set_table_num, array('id' => 'caExporterList'), array('width' => '135px'));
                $vs_buf .= caHTMLHiddenInput('set_id', array('value' => $t_item->getPrimaryKey()));
                $vs_buf .= caFormSubmitLink($po_view->request, _t('Export') . " &rsaquo;", "button", "caExportForm");
                $vs_buf .= "</div>\n";
                $vs_buf .= "</form>";
                $vs_buf .= "</div>";
                $vs_buf .= "<script type='text/javascript'>";
                $vs_buf .= "jQuery(document).ready(function() {";
                $vs_buf .= "jQuery(\"#exporterFormList\").hide();";
                $vs_buf .= "});";
                $vs_buf .= "</script>";
            }
        }
        //
        // Output extra useful info for set items
        //
        if ($vs_table_name === 'ca_set_items') {
            AssetLoadManager::register("panel");
            $t_set = new ca_sets();
            if ($t_set->load($vn_set_id = $t_item->get('set_id'))) {
                $vs_buf .= "<div><strong>" . _t("Part of set") . "</strong>: " . caEditorLink($po_view->request, $t_set->getLabelForDisplay(), '', 'ca_sets', $vn_set_id) . "<br/>\n";
                $t_content_instance = $t_item->getAppDatamodel()->getInstanceByTableNum($vn_item_table_num = $t_item->get('table_num'));
                if ($t_content_instance->load($vn_row_id = $t_item->get('row_id'))) {
                    $vs_label = $t_content_instance->getLabelForDisplay();
                    if ($vs_id_fld = $t_content_instance->getProperty('ID_NUMBERING_ID_FIELD')) {
                        $vs_label .= " (" . $t_content_instance->get($vs_id_fld) . ")";
                    }
                    $vs_buf .= "<strong>" . _t("Is %1", caGetTableDisplayName($vn_item_table_num, false) . "</strong>: " . caEditorLink($po_view->request, $vs_label, '', $vn_item_table_num, $vn_row_id)) . "<br/>\n";
                }
                $vs_buf .= "</div>\n";
            }
        }
        //
        // Output extra useful info for lists
        //
        if ($vs_table_name === 'ca_lists' && $t_item->getPrimaryKey()) {
            $vs_buf .= "<strong>" . _t("Number of items") . "</strong>: " . $t_item->numItemsInList() . "<br/>\n";
            $t_list_item = new ca_list_items();
            $t_list_item->load(array('list_id' => $t_item->getPrimaryKey(), 'parent_id' => null));
            $vs_type_list = $t_list_item->getTypeListAsHTMLFormElement('type_id', array('style' => 'width: 90px; font-size: 9px;'), array('access' => __CA_BUNDLE_ACCESS_EDIT__));
            if ($vs_type_list) {
                $vs_buf .= '<div style="border-top: 1px solid #aaaaaa; margin-top: 5px; font-size: 10px;">';
                $vs_buf .= caFormTag($po_view->request, 'Edit', 'NewChildForm', 'administrate/setup/list_item_editor/ListItemEditor', 'post', 'multipart/form-data', '_top', array('disableUnsavedChangesWarning' => true));
                $vs_buf .= _t('Add a %1 to this list', $vs_type_list) . caHTMLHiddenInput($t_list_item->primaryKey(), array('value' => '0')) . caHTMLHiddenInput('parent_id', array('value' => $t_list_item->getPrimaryKey()));
                $vs_buf .= caFormSubmitLink($po_view->request, caNavIcon($po_view->request, __CA_NAV_BUTTON_ADD__), '', 'NewChildForm');
                $vs_buf .= "</form></div>\n";
            }
        }
        //
        // Output containing list for list items
        //
        if ($vs_table_name === 'ca_list_items') {
            if ($t_list = $po_view->getVar('t_list')) {
                $vn_list_id = $t_list->getPrimaryKey();
                $vs_buf .= "<strong>" . _t("Part of") . "</strong>: " . caEditorLink($po_view->request, $t_list->getLabelForDisplay(), '', 'ca_lists', $vn_list_id) . "<br/>\n";
                if ($t_item->get('is_default')) {
                    $vs_buf .= "<strong>" . _t("Is default for list") . "</strong><br/>\n";
                }
            }
        }
        //
        // Output containing relationship type name for relationship types
        //
        if ($vs_table_name === 'ca_relationship_types') {
            if (!($t_rel_instance = $t_item->getAppDatamodel()->getInstanceByTableNum($t_item->get('table_num'), true))) {
                if ($vn_parent_id = $po_view->request->getParameter('parent_id', pInteger)) {
                    $t_rel_type = new ca_relationship_types($vn_parent_id);
                    $t_rel_instance = $t_item->getAppDatamodel()->getInstanceByTableNum($t_rel_type->get('table_num'), true);
                }
            }
            if ($t_rel_instance) {
                $vs_buf .= "<div><strong>" . _t("Is a") . "</strong>: " . $t_rel_instance->getProperty('NAME_SINGULAR') . "<br/></div>\n";
            }
        }
        //
        // Output extra useful info for metadata elements
        //
        if ($vs_table_name === 'ca_metadata_elements' && $t_item->getPrimaryKey()) {
            $vs_buf .= "<div><strong>" . _t("Element code") . "</strong>: " . $t_item->get('element_code') . "<br/></div>\n";
            if (sizeof($va_uis = $t_item->getUIs()) > 0) {
                $vs_buf .= "<div><strong>" . _t("Referenced by user interfaces") . "</strong>:<br/>\n";
                foreach ($va_uis as $vn_ui_id => $va_ui_info) {
                    $vs_buf .= caNavLink($po_view->request, $va_ui_info['name'], '', 'administrate/setup/interface_screen_editor', 'InterfaceScreenEditor', 'Edit', array('ui_id' => $vn_ui_id, 'screen_id' => $va_ui_info['screen_id']));
                    $vs_buf .= " (" . $o_dm->getTableProperty($va_ui_info['editor_type'], 'NAME_PLURAL') . ")<br/>\n";
                }
                $vs_buf .= "</div>\n";
            }
        }
        //
        // Output related objects for ca_editor_uis and ca_editor_ui_screens
        //
        if ($vs_table_name === 'ca_editor_uis') {
            $vs_buf .= "<div><strong>" . _t("Number of screens") . "</strong>: " . (int) $t_item->getScreenCount() . "\n";
            if ($t_item->getPrimaryKey()) {
                $vs_buf .= "<div><strong>" . _t("Edits") . "</strong>: " . caGetTableDisplayName($t_item->get('editor_type')) . "<br/>\n";
            } else {
                $vs_buf .= "<div><strong>" . _t("Edits") . "</strong>: " . caGetTableDisplayName($po_view->request->getParameter('editor_type', pInteger)) . "<br/>\n";
            }
            $vs_buf .= "</div>\n";
        }
        //
        // Output related objects for ca_editor_uis and ca_editor_ui_screens
        //
        if ($vs_table_name === 'ca_editor_ui_screens') {
            $t_ui = new ca_editor_uis($vn_ui_id = $t_item->get('ui_id'));
            $vs_buf .= "<div><strong>" . _t("Part of") . "</strong>: " . caNavLink($po_view->request, $t_ui->getLabelForDisplay(), '', 'administrate/setup/interface_editor', 'InterfaceEditor', 'Edit', array('ui_id' => $vn_ui_id)) . "\n";
            $vs_buf .= "</div>\n";
        }
        //
        // Output extra useful info for bundle displays
        //
        if ($vs_table_name === 'ca_bundle_displays') {
            $vs_buf .= "<div><strong>" . _t("Number of placements") . "</strong>: " . $t_item->getPlacementCount(array('user_id' => $po_view->request->getUserID())) . "<br/>\n";
            if ($t_item->getPrimaryKey()) {
                $vn_content_table_num = $t_item->get('table_num');
                $vs_buf .= "<strong>" . _t("Type of content") . "</strong>: " . caGetTableDisplayName($vn_content_table_num) . "\n";
                $vs_buf .= "</div>\n";
            } else {
                if ($vn_content_table_num = $po_view->request->getParameter('table_num', pInteger)) {
                    $vs_buf .= "<div><strong>" . _t("Type of content") . "</strong>: " . caGetTableDisplayName($vn_content_table_num) . "\n";
                    $vs_buf .= "</div>\n";
                }
            }
            $t_user = new ca_users(($vn_user_id = $t_item->get('user_id')) ? $vn_user_id : $po_view->request->getUserID());
            if ($t_user->getPrimaryKey()) {
                $vs_buf .= "<div><strong>" . _t('Owner') . "</strong>: " . $t_user->get('fname') . ' ' . $t_user->get('lname') . "</div>\n";
            }
        }
        //
        // Output extra useful info for search forms
        //
        if ($vs_table_name === 'ca_search_forms') {
            $vs_buf .= "<div><strong>" . _t("Number of placements") . "</strong>: " . $t_item->getPlacementCount(array('user_id' => $po_view->request->getUserID())) . "<br/>\n";
            if ($t_item->getPrimaryKey()) {
                $vn_content_table_num = $t_item->get('table_num');
                $vs_buf .= "<strong>" . _t("Searches for") . "</strong>: " . caGetTableDisplayName($vn_content_table_num) . "\n";
                $vs_buf .= "</div>\n";
            } else {
                if ($vn_content_table_num = $po_view->request->getParameter('table_num', pInteger)) {
                    $vs_buf .= "<strong>" . _t("Searches for") . "</strong>: " . caGetTableDisplayName($vn_content_table_num) . "\n";
                    $vs_buf .= "</div>\n";
                }
            }
            $t_user = new ca_users(($vn_user_id = $t_item->get('user_id')) ? $vn_user_id : $po_view->request->getUserID());
            if ($t_user->getPrimaryKey()) {
                $vs_buf .= "<div><strong>" . _t('Owner') . "</strong>: " . $t_user->get('fname') . ' ' . $t_user->get('lname') . "</div>\n";
            }
        }
        //
        // Output extra useful info for tours
        //
        if ($vs_table_name === 'ca_tours' && $t_item->getPrimaryKey()) {
            $vs_buf .= "<br/><strong>" . _t("Number of stops") . "</strong>: " . $t_item->getStopCount() . "<br/>\n";
        }
        //
        // Output containing tour for tour stops
        //
        if ($vs_table_name === 'ca_tour_stops') {
            $t_tour = new ca_tours($vn_tour_id = $t_item->get('tour_id'));
            $vs_buf .= "<strong>" . _t("Part of") . "</strong>: " . caEditorLink($po_view->request, $t_tour->getLabelForDisplay(), '', 'ca_tours', $vn_tour_id) . "<br/>\n";
        }
        //
        // Output extra useful info for bundle mappings
        //
        if ($vs_table_name === 'ca_bundle_mappings') {
            if ($t_item->getPrimaryKey()) {
                $vn_content_table_num = $t_item->get('table_num');
                $vs_buf .= "<br/><strong>" . _t("Type of content") . "</strong>: " . caGetTableDisplayName($vn_content_table_num) . "<br/>\n";
                $vs_buf .= "<strong>" . _t("Type") . "</strong>: " . $t_item->getChoiceListValue('direction', $t_item->get('direction')) . "<br/>\n";
                $vs_buf .= "<strong>" . _t("Target format") . "</strong>: " . $t_item->get('target') . "<br/>\n";
                $va_stats = $t_item->getMappingStatistics();
                $vs_buf .= "<div><strong>" . _t("Number of groups") . "</strong>: " . $va_stats['groupCount'] . "<br/>\n";
                $vs_buf .= "<strong>" . _t("Number of rules") . "</strong>: " . $va_stats['ruleCount'] . "<br/>\n";
                $vs_buf .= "</div>\n";
            } else {
                if ($vn_content_table_num = $po_view->request->getParameter('table_num', pInteger)) {
                    $vs_buf .= "<div><strong>" . _t("Type of content") . "</strong>: " . caGetTableDisplayName($vn_content_table_num) . "<br/>\n";
                    $vs_buf .= "<strong>" . _t("Type") . "</strong>: " . $t_item->getChoiceListValue('direction', $po_view->request->getParameter('direction', pString)) . "<br/>\n";
                    $vs_buf .= "<strong>" . _t("Target format") . "</strong>: " . $po_view->request->getParameter('target', pString) . "<br/>\n";
                    $vs_buf .= "<div><strong>" . _t("Number of groups") . "</strong>: 0<br/>\n";
                    $vs_buf .= "<strong>" . _t("Number of rules") . "</strong>: 0</div>\n";
                    $vs_buf .= "</div>\n";
                }
            }
        }
        //
        // Output extra useful info for client services/commerce orders
        //
        if ($vs_table_name === 'ca_commerce_orders') {
            $o_client_services_config = Configuration::load($po_view->request->config->get('client_services_config'));
            $va_order_totals = $t_item->getOrderTotals();
            if ($va_order_totals['fee'] + $va_order_totals['tax'] + $va_order_totals['shipping'] + $va_order_totals['handling'] + $va_order_totals['additional_order_fees'] + $va_order_totals['additional_item_fees'] != 0) {
                $vs_currency_symbol = $o_client_services_config->get('currency_symbol');
                $vs_buf .= "<table style='margin-left: 10px;'>";
                $vs_buf .= "<tr><td><strong>" . _t("Items") . '</strong></td><td>' . $vs_currency_symbol . sprintf("%4.2f", $va_order_totals['fee']) . " (" . (int) $va_order_totals['items'] . ")</td></tr>\n";
                $vs_buf .= "<tr><td><strong>" . _t("S+H") . '</strong></td><td>' . $vs_currency_symbol . sprintf("%4.2f", $va_order_totals['shipping'] + $va_order_totals['handling']) . "</td></tr>\n";
                $vs_buf .= "<tr><td><strong>" . _t("Tax") . '</strong></td><td>' . $vs_currency_symbol . sprintf("%4.2f", $va_order_totals['tax']) . "</td></tr>\n";
                $vs_buf .= "<tr><td><strong>" . _t("Addtl fees") . '</strong></td><td>' . $vs_currency_symbol . sprintf("%4.2f", $va_order_totals['additional_order_fees'] + $va_order_totals['additional_item_fees']) . "</td></tr>\n";
                $vs_buf .= "<tr><td><strong>" . _t("Total") . '</strong></td><td>' . $vs_currency_symbol . sprintf("%4.2f", $va_order_totals['fee'] + $va_order_totals['tax'] + $va_order_totals['shipping'] + $va_order_totals['handling'] + $va_order_totals['additional_order_fees'] + $va_order_totals['additional_item_fees']) . "</td></tr>\n";
                $vs_buf .= "</table>";
                $vs_buf .= "<strong>" . $t_item->getFieldInfo('payment_status', 'LABEL') . "</strong>: " . $t_item->getChoiceListValue('payment_status', $t_item->get('payment_status')) . "<br/>\n";
            }
            $vs_buf .= "<br/><strong>" . $t_item->getFieldInfo('order_status', 'LABEL') . "</strong>: " . $t_item->getChoiceListValue('order_status', $t_item->get('order_status')) . "<br/>\n";
            if ($vs_shipping_date = $t_item->get('shipping_date', array('dateFormat' => 'delimited', 'timeOmit' => true))) {
                $vs_buf .= "<strong>" . $t_item->getFieldInfo('shipping_date', 'LABEL') . "</strong>: " . $vs_shipping_date;
                if ($vs_shipped_on_date = $t_item->get('shipped_on_date', array('dateFormat' => 'delimited'))) {
                    $vs_buf .= " (" . _t('shipped %1', $vs_shipped_on_date) . ")";
                } else {
                    $vs_buf .= " (" . _t('not shipped') . ")";
                }
                $vs_buf .= "<br/>\n";
            }
            if (($vn_shipping_method = $t_item->get('shipping_method')) && $t_item->getChoiceListValue('shipping_method', $vn_shipping_method) != 'None') {
                $vs_buf .= "<strong>" . $t_item->getFieldInfo('shipping_method', 'LABEL') . "</strong>: " . $t_item->getChoiceListValue('shipping_method', $vn_shipping_method) . "<br/>\n";
            }
        }
        //
        // Output configurable additional info from config, if set
        //
        if ($vs_additional_info = $po_view->request->config->get("{$vs_table_name}_inspector_additional_info")) {
            if (is_array($vs_additional_info)) {
                $vs_buf .= "<br/>";
                foreach ($vs_additional_info as $vs_info) {
                    $vs_buf .= caProcessTemplateForIDs($vs_info, $vs_table_name, array($t_item->getPrimaryKey()), array('requireLinkTags' => true)) . "<br/>\n";
                }
            } else {
                $vs_buf .= "<br/>" . caProcessTemplateForIDs($vs_additional_info, $vs_table_name, array($t_item->getPrimaryKey()), array('requireLinkTags' => true)) . "<br/>\n";
            }
        }
        // -------------------------------------------------------------------------------------
        // Export
        if ($t_item->getPrimaryKey() && $po_view->request->config->get($vs_table_name . '_show_add_child_control_in_inspector')) {
            $vb_show_add_child_control = true;
            if (is_array($va_restrict_add_child_control_to_types = $po_view->request->config->getList($vs_table_name . '_restrict_child_control_in_inspector_to_types')) && sizeof($va_restrict_add_child_control_to_types)) {
                $t_type_instance = $t_item->getTypeInstance();
                if (!in_array($t_type_instance->get('idno'), $va_restrict_add_child_control_to_types) && !in_array($t_type_instance->getPrimaryKey(), $va_restrict_add_child_control_to_types)) {
                    $vb_show_add_child_control = false;
                }
            }
        }
        if ($po_view->request->user->canDoAction('can_export_' . $vs_table_name) && $t_item->getPrimaryKey() && sizeof(ca_data_exporters::getExporters($t_item->tableNum())) > 0) {
            $vs_buf .= '<div style="border-top: 1px solid #aaaaaa; margin-top: 5px; font-size: 10px; text-align: right;" id="caExportItemButton">';
            $vs_buf .= _t('Export this %1', mb_strtolower($vs_type_name, 'UTF-8')) . " ";
            $vs_buf .= "<a class='button' onclick='jQuery(\"#exporterFormList\").show();' style='text-align:right;' href='#'>" . caNavIcon($po_view->request, __CA_NAV_BUTTON_ADD__) . "</a>";
            $vs_buf .= caFormTag($po_view->request, 'ExportSingleData', 'caExportForm', 'manage/MetadataExport', 'post', 'multipart/form-data', '_top', array('disableUnsavedChangesWarning' => true));
            $vs_buf .= "<div id='exporterFormList'>";
            $vs_buf .= ca_data_exporters::getExporterListAsHTMLFormElement('exporter_id', $t_item->tableNum(), array('id' => 'caExporterList'), array('width' => '120px'));
            $vs_buf .= caHTMLHiddenInput('item_id', array('value' => $t_item->getPrimaryKey()));
            $vs_buf .= caFormSubmitLink($po_view->request, _t('Export') . " &rsaquo;", "button", "caExportForm");
            $vs_buf .= "</div>\n";
            $vs_buf .= "</form>";
            $vs_buf .= "</div>";
            $vs_buf .= "<script type='text/javascript'>";
            $vs_buf .= "jQuery(document).ready(function() {";
            $vs_buf .= "jQuery(\"#exporterFormList\").hide();";
            $vs_buf .= "});";
            $vs_buf .= "</script>";
        }
        $vs_buf .= "</div></h4>\n";
        $vs_buf .= "<script type='text/javascript'>\n\t\t\tvar inspectorCookieJar = jQuery.cookieJar('caCookieJar');";
        if ($t_item->getPrimaryKey()) {
            if ($vs_more_info) {
                $vs_buf .= "\t\t\t\n\t\t\tif (inspectorCookieJar.get('inspectorMoreInfoIsOpen') == undefined) {\t\t// default is to have info open\n\t\t\t\tinspectorCookieJar.set('inspectorMoreInfoIsOpen', 1);\n\t\t\t}\n\t\t\tif (inspectorCookieJar.get('inspectorMoreInfoIsOpen') == 1) {\n\t\t\t\tjQuery('#inspectorInfo').toggle(0);\n\t\t\t\tjQuery('#inspectorMoreInfo').html('" . addslashes(caNavIcon($po_view->request, __CA_NAV_BUTTON_COLLAPSE__)) . "');\n\t\t\t}\n\t\t\n\t\t\tjQuery('#inspectorMoreInfo').click(function() {\n\t\t\t\tjQuery('#inspectorInfo').slideToggle(350, function() { \n\t\t\t\t\tinspectorCookieJar.set('inspectorMoreInfoIsOpen', (this.style.display == 'block') ? 1 : 0); \n\t\t\t\t\tjQuery('#inspectorMoreInfo').html((this.style.display == 'block') ? '" . addslashes(caNavIcon($po_view->request, __CA_NAV_BUTTON_COLLAPSE__)) . "' : '" . addslashes(caNavIcon($po_view->request, __CA_NAV_BUTTON_INFO2__)) . "');\n\t\t\t\t\tcaResizeSideNav();\n\t\t\t\t}); \n\t\t\t\treturn false;\n\t\t\t});\n\t\t";
            }
            if (sizeof($va_reps)) {
                $vs_buf .= "\n\t\tif (inspectorCookieJar.get('inspectorShowMediaIsOpen') == undefined) {\t\t// default is to have media open\n\t\t\tinspectorCookieJar.set('inspectorShowMediaIsOpen', 1);\n\t\t}\n\t\t\n\t\tif (inspectorCookieJar.get('inspectorShowMediaIsOpen') == 1) {\n\t\t\tjQuery('#inspectorMedia').toggle();\n\t\t}\n\t\n\t\tjQuery('#caColorbox').on('click', function(e) {\n\t\t\tif (e.altKey) {\n\t\t\t\tjQuery('#inspectorMedia').slideToggle(200, function() { \n\t\t\t\t\tinspectorCookieJar.set('inspectorShowMediaIsOpen', (this.style.display == 'block') ? 1 : 0); \n\t\t\t\t\t\tcaResizeSideNav();\n\t\t\t\t}); \n\t\t\t\treturn false;\n\t\t\t}\n\t\t});\n\t\t\t\t\t";
            }
        }
        $vs_buf .= "</script>\n";
    }
    $o_app_plugin_manager = new ApplicationPluginManager();
    $va_hookAppend = $o_app_plugin_manager->hookAppendToEditorInspector(array("t_item" => $t_item));
    if (is_string($va_hookAppend["caEditorInspectorAppend"])) {
        $vs_buf .= $va_hookAppend["caEditorInspectorAppend"];
    }
    return $vs_buf;
}
<?php

$t_object = $this->getVar("item");
$vn_object_id = $t_object->get('ca_objects.object_id');
$va_comments = $this->getVar("comments");
$pn_rep_id = $this->getVar("representation_id");
$va_export_formats = $this->getVar('export_formats');
$vs_export_format_select = $this->getVar('export_format_select');
$t_set = new ca_sets();
$va_sets = caExtractValuesByUserLocale($t_set->getSetsForItem("ca_objects", $t_object->get("object_id"), array("user_id" => $this->request->user->get("user_id"))));
$va_lightbox_crumbs = array();
foreach ($va_sets as $vn_set_id => $va_set) {
    $va_lightbox_crumbs[] = caNavLink($this->request, _t("Lightbox"), "", "", "Sets", "Index") . " &#8594; " . caNavLink($this->request, $va_set["name"], "", "", "Sets", "SetDetail", array("set_id" => $vn_set_id)) . " &#8594; " . $t_object->get("ca_objects.preferred_labels.name");
}
$vs_lightbox_crumbs = "";
if (sizeof($va_lightbox_crumbs)) {
    $vs_lightbox_crumbs = join("<br/>", $va_lightbox_crumbs);
}
?>
<div class="row">
	<div class='col-xs-1 col-sm-1 col-md-1 col-lg-1'>
		<div class="detailNavBgLeft">
			{{{resultsLink}}}<div class='detailPrevLink'>{{{previousLink}}}</div>
		</div><!-- end detailNavBgLeft -->
	</div><!-- end col -->
	<div class='col-xs-10 col-sm-10 col-md-10 col-lg-10'>
	
	</div>
	<div class='col-xs-1 col-sm-1 col-md-1 col-lg-1'>
		<div class="detailNavBgRight">
			{{{nextLink}}}
Пример #3
0
 /**
  * Returns list of sets item is member of
  *
  * @param string $type can be one of: ["ca_objects", "ca_entities", "ca_places", "ca_occurrences", "ca_collections", "ca_list_items", "ca_object_representations", "ca_storage_locations", "ca_movements", "ca_loans", "ca_tours", "ca_tour_stops"]
  * @param int $item_id primary key
  * @return array
  */
 public function getSetsForItem($type, $item_id)
 {
     if (!$this->getTableInstance($type, $item_id)) {
         throw new SoapFault("Server", "Invalid type or ID");
     }
     $t_set = new ca_sets();
     return $t_set->getSetsForItem($type, $item_id, array('user_id' => $this->opo_request->getUserID()));
 }
 /**
  * Saves all bundles on the specified screen in the database by extracting 
  * required data from the supplied request
  * $pm_screen can be a screen tag (eg. "Screen5") or a screen_id (eg. 5)
  *
  * Calls processBundlesBeforeBaseModelSave() method in subclass right before invoking insert() or update() on
  * the BaseModel, if the method is defined. Passes the following parameters to processBundlesBeforeBaseModelSave():
  *		array $pa_bundles An array of bundles to be saved
  *		string $ps_form_prefix The form prefix
  *		RequestHTTP $po_request The current request
  *		array $pa_options Optional array of parameters; expected to be the same as that passed to saveBundlesForScreen()
  *
  * The processBundlesBeforeBaseModelSave() is useful for those odd cases where you need to do some processing before the basic
  * database record defined by the model (eg. intrinsic fields and hierarchy coding) is inserted or updated. You usually don't need 
  * to use it.
  *
  * @param mixed $pm_screen
  * @param RequestHTTP $ps_request
  * @param array $pa_options Options are:
  *		dryRun = Go through the motions of saving but don't actually write information to the database
  *		batch = Process save in "batch" mode. Specifically this means honoring batch mode settings (add, replace, remove), skipping bundles that are not supported in batch mode and ignoring updates
  *		existingRepresentationMap = an array of representation_ids key'ed on file path. If set saveBundlesForScreen() use link the specified representation to the row it is saving rather than processing the uploaded file. saveBundlesForScreen() will build the map as it goes, adding newly uploaded files. If you want it to process a file in a batch situation where it should be processed the first time and linked subsequently then pass an empty array here. saveBundlesForScreen() will use the empty array to build the map.
  */
 public function saveBundlesForScreen($pm_screen, $po_request, &$pa_options)
 {
     $vb_we_set_transaction = false;
     $vs_form_prefix = caGetOption('formName', $pa_options, $po_request->getParameter('_formName', pString));
     $vb_dryrun = caGetOption('dryRun', $pa_options, false);
     $vb_batch = caGetOption('batch', $pa_options, false);
     if (!$this->inTransaction()) {
         $this->setTransaction(new Transaction($this->getDb()));
         $vb_we_set_transaction = true;
     } else {
         if ($vb_dryrun) {
             $this->postError(799, _t('Cannot do dry run save when in transaction. Try again without setting a transaction.'), "BundlableLabelableBaseModelWithAttributes->saveBundlesForScreen()");
             return false;
         }
     }
     $vb_read_only_because_deaccessioned = $this->hasField('is_deaccessioned') && (bool) $this->getAppConfig()->get('deaccession_dont_allow_editing') && (bool) $this->get('is_deaccessioned');
     BaseModel::setChangeLogUnitID();
     // get items on screen
     $t_ui = caGetOption('ui_instance', $pa_options, ca_editor_uis::loadDefaultUI($this->tableName(), $po_request, $this->getTypeID()));
     $va_bundle_lists = $this->getBundleListsForScreen($pm_screen, $po_request, $t_ui, $pa_options);
     //
     // Filter bundles to save if deaccessioned - only allow editing of the ca_objects_deaccession bundle
     //
     if ($vb_read_only_because_deaccessioned) {
         foreach ($va_bundle_lists['bundles'] as $vn_i => $va_bundle) {
             if ($va_bundle['bundle_name'] !== 'ca_objects_deaccession') {
                 unset($va_bundle_lists['bundles'][$vn_i]);
             }
         }
         foreach ($va_bundle_lists['fields_by_type'] as $vs_type => $va_bundles) {
             foreach ($va_bundles as $vs_id => $vs_bundle_name) {
                 if ($vs_bundle_name !== 'ca_objects_deaccession') {
                     unset($va_bundle_lists['fields_by_type'][$vs_type][$vs_id]);
                 }
             }
         }
     }
     $va_bundles = $va_bundle_lists['bundles'];
     $va_fields_by_type = $va_bundle_lists['fields_by_type'];
     // save intrinsic fields
     if (is_array($va_fields_by_type['intrinsic'])) {
         $vs_idno_field = $this->getProperty('ID_NUMBERING_ID_FIELD');
         foreach ($va_fields_by_type['intrinsic'] as $vs_placement_code => $vs_f) {
             if ($vb_batch) {
                 $vs_batch_mode = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_batch_mode", pString);
                 if ($vs_batch_mode == '_disabled_') {
                     continue;
                 }
             }
             if (isset($_FILES["{$vs_placement_code}{$vs_form_prefix}{$vs_f}"]) && $_FILES["{$vs_placement_code}{$vs_form_prefix}{$vs_f}"]) {
                 // media field
                 $this->set($vs_f, $_FILES["{$vs_placement_code}{$vs_form_prefix}{$vs_f}"]['tmp_name'], array('original_filename' => $_FILES["{$vs_placement_code}{$vs_form_prefix}{$vs_f}"]['name']));
             } else {
                 switch ($vs_f) {
                     case 'access':
                         if ((bool) $this->getAppConfig()->get($this->tableName() . '_allow_access_inheritance') && $this->hasField('access_inherit_from_parent')) {
                             $this->set('access_inherit_from_parent', $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}access_inherit_from_parent", pInteger));
                         }
                         if (!(bool) $this->getAppConfig()->get($this->tableName() . '_allow_access_inheritance') || !$this->hasField('access_inherit_from_parent') || !(bool) $this->get('access_inherit_from_parent')) {
                             $this->set('access', $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}access", pString));
                         }
                         break;
                     case $vs_idno_field:
                         if ($this->opo_idno_plugin_instance) {
                             $this->opo_idno_plugin_instance->setDb($this->getDb());
                             $this->set($vs_f, $vs_tmp = $this->opo_idno_plugin_instance->htmlFormValue($vs_idno_field));
                         } else {
                             $this->set($vs_f, $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}{$vs_f}", pString));
                         }
                         break;
                     default:
                         // Look for fully qualified intrinsic
                         if (!strlen($vs_v = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}{$vs_f}", pString))) {
                             // fall back to simple field name intrinsic spec - still used for "mandatory" fields such as type_id and parent_id
                             $vs_v = $po_request->getParameter("{$vs_f}", pString);
                         }
                         $this->set($vs_f, $vs_v);
                         break;
                 }
             }
             if ($this->numErrors() > 0) {
                 foreach ($this->errors() as $o_e) {
                     switch ($o_e->getErrorNumber()) {
                         case 795:
                             // field conflicts
                             foreach ($this->getFieldConflicts() as $vs_conflict_field) {
                                 $po_request->addActionError($o_e, $vs_conflict_field);
                             }
                             break;
                         default:
                             $po_request->addActionError($o_e, $vs_f);
                             break;
                     }
                 }
             }
         }
     }
     // save attributes
     $va_inserted_attributes_by_element = array();
     if (isset($va_fields_by_type['attribute']) && is_array($va_fields_by_type['attribute'])) {
         //
         // name of attribute request parameters are:
         // 	For new attributes
         // 		{$vs_form_prefix}_attribute_{element_set_id}_{element_id|'locale_id'}_new_{n}
         //		ex. ObjectBasicForm_attribute_6_locale_id_new_0 or ObjectBasicForm_attribute_6_desc_type_new_0
         //
         // 	For existing attributes:
         // 		{$vs_form_prefix}_attribute_{element_set_id}_{element_id|'locale_id'}_{attribute_id}
         //
         // look for newly created attributes; look for attributes to delete
         $va_inserted_attributes = array();
         $reserved_elements = array();
         foreach ($va_fields_by_type['attribute'] as $vs_placement_code => $vs_f) {
             $vs_element_set_code = preg_replace("/^ca_attribute_/", "", $vs_f);
             //does the attribute's datatype have a saveElement method - if so, use that instead
             $vs_element = $this->_getElementInstance($vs_element_set_code);
             $vn_element_id = $vs_element->getPrimaryKey();
             $vs_element_datatype = $vs_element->get('datatype');
             $vs_datatype = Attribute::getValueInstance($vs_element_datatype);
             if (method_exists($vs_datatype, 'saveElement')) {
                 $reserved_elements[] = $vs_element;
                 continue;
             }
             $va_attributes_to_insert = array();
             $va_attributes_to_delete = array();
             $va_locales = array();
             $vs_batch_mode = $_REQUEST[$vs_placement_code . $vs_form_prefix . '_attribute_' . $vn_element_id . '_batch_mode'];
             if ($vb_batch && $vs_batch_mode == '_delete_') {
                 // Remove all attributes and continue
                 $this->removeAttributes($vn_element_id, array('force' => true));
                 continue;
             }
             foreach ($_REQUEST as $vs_key => $vs_val) {
                 // is it a newly created attribute?
                 if (preg_match('/' . $vs_placement_code . $vs_form_prefix . '_attribute_' . $vn_element_id . '_([\\w\\d\\-_]+)_new_([\\d]+)/', $vs_key, $va_matches)) {
                     if ($vb_batch) {
                         switch ($vs_batch_mode) {
                             case '_disabled_':
                                 // skip
                                 continue 2;
                                 break;
                             case '_add_':
                                 // just try to add attribute as in normal non-batch save
                                 // noop
                                 break;
                             case '_replace_':
                                 // remove all existing attributes before trying to save
                                 $this->removeAttributes($vn_element_id, array('force' => true));
                                 continue;
                                 break;
                         }
                     }
                     $vn_c = intval($va_matches[2]);
                     // yep - grab the locale and value
                     $vn_locale_id = isset($_REQUEST[$vs_placement_code . $vs_form_prefix . '_attribute_' . $vn_element_id . '_locale_id_new_' . $vn_c]) ? $_REQUEST[$vs_placement_code . $vs_form_prefix . '_attribute_' . $vn_element_id . '_locale_id_new_' . $vn_c] : null;
                     $va_inserted_attributes_by_element[$vn_element_id][$vn_c]['locale_id'] = $va_attributes_to_insert[$vn_c]['locale_id'] = $vn_locale_id;
                     $va_inserted_attributes_by_element[$vn_element_id][$vn_c][$va_matches[1]] = $va_attributes_to_insert[$vn_c][$va_matches[1]] = $vs_val;
                 } else {
                     // is it a delete key?
                     if (preg_match('/' . $vs_placement_code . $vs_form_prefix . '_attribute_' . $vn_element_id . '_([\\d]+)_delete/', $vs_key, $va_matches)) {
                         $vn_attribute_id = intval($va_matches[1]);
                         $va_attributes_to_delete[$vn_attribute_id] = true;
                     }
                 }
             }
             // look for uploaded files as attributes
             foreach ($_FILES as $vs_key => $va_val) {
                 if (preg_match('/' . $vs_placement_code . $vs_form_prefix . '_attribute_' . $vn_element_id . '_locale_id_new_([\\d]+)/', $vs_key, $va_locale_matches)) {
                     $vn_locale_c = intval($va_locale_matches[1]);
                     $va_locales[$vn_locale_c] = $vs_val;
                     continue;
                 }
                 // is it a newly created attribute?
                 if (preg_match('/' . $vs_placement_code . $vs_form_prefix . '_attribute_' . $vn_element_id . '_([\\w\\d\\-_]+)_new_([\\d]+)/', $vs_key, $va_matches)) {
                     if (!$va_val['size']) {
                         continue;
                     }
                     // skip empty files
                     // yep - grab the value
                     $vn_c = intval($va_matches[2]);
                     $va_inserted_attributes_by_element[$vn_element_id][$vn_c]['locale_id'] = $va_attributes_to_insert[$vn_c]['locale_id'] = $va_locales[$vn_c];
                     $va_val['_uploaded_file'] = true;
                     $va_inserted_attributes_by_element[$vn_element_id][$vn_c][$va_matches[1]] = $va_attributes_to_insert[$vn_c][$va_matches[1]] = $va_val;
                 }
             }
             if (!$vb_batch) {
                 // do deletes
                 $this->clearErrors();
                 foreach ($va_attributes_to_delete as $vn_attribute_id => $vb_tmp) {
                     $this->removeAttribute($vn_attribute_id, $vs_f, array('pending_adds' => $va_attributes_to_insert));
                 }
             }
             // do inserts
             foreach ($va_attributes_to_insert as $va_attribute_to_insert) {
                 $this->clearErrors();
                 $this->addAttribute($va_attribute_to_insert, $vn_element_id, $vs_f);
             }
             if (!$vb_batch) {
                 // check for attributes to update
                 if (is_array($va_attrs = $this->getAttributesByElement($vn_element_id))) {
                     $t_element = new ca_metadata_elements();
                     $va_attrs_update_list = array();
                     foreach ($va_attrs as $o_attr) {
                         $this->clearErrors();
                         $vn_attribute_id = $o_attr->getAttributeID();
                         if (isset($va_inserted_attributes[$vn_attribute_id]) && $va_inserted_attributes[$vn_attribute_id]) {
                             continue;
                         }
                         if (isset($va_attributes_to_delete[$vn_attribute_id]) && $va_attributes_to_delete[$vn_attribute_id]) {
                             continue;
                         }
                         $vn_element_set_id = $o_attr->getElementID();
                         $va_attr_update = array('locale_id' => $po_request->getParameter($vs_placement_code . $vs_form_prefix . '_attribute_' . $vn_element_set_id . '_locale_id_' . $vn_attribute_id, pString));
                         //
                         // Check to see if there are any values in the element set that are not in the  attribute we're editing
                         // If additional sub-elements were added to the set after the attribute we're updating was created
                         // those sub-elements will not have corresponding values returned by $o_attr->getValues() above.
                         // Because we use the element_ids in those values to pull request parameters, if an element_id is missing
                         // it effectively becomes invisible and cannot be set. This is a fairly unusual case but it happens, and when it does
                         // it's really annoying. It would be nice and efficient to simply create the missing values at configuration time, but we wouldn't
                         // know what to set the values to. So what we do is, after setting all of the values present in the attribute from the request, grab
                         // the configuration for the element set and see if there are any elements in the set that we didn't get values for.
                         //
                         $va_sub_elements = $t_element->getElementsInSet($vn_element_set_id);
                         foreach ($va_sub_elements as $vn_i => $va_element_info) {
                             if ($va_element_info['datatype'] == 0) {
                                 continue;
                             }
                             //$vn_element_id = $o_attr_val->getElementID();
                             $vn_element_id = $va_element_info['element_id'];
                             $vs_k = $vs_placement_code . $vs_form_prefix . '_attribute_' . $vn_element_set_id . '_' . $vn_element_id . '_' . $vn_attribute_id;
                             if (isset($_FILES[$vs_k]) && ($va_val = $_FILES[$vs_k])) {
                                 if ($va_val['size'] > 0) {
                                     // is there actually a file?
                                     $va_val['_uploaded_file'] = true;
                                     $va_attr_update[$vn_element_id] = $va_val;
                                     continue;
                                 }
                             }
                             $vs_attr_val = $po_request->getParameter($vs_k, pString);
                             $va_attr_update[$vn_element_id] = $vs_attr_val;
                         }
                         $this->clearErrors();
                         $this->editAttribute($vn_attribute_id, $vn_element_set_id, $va_attr_update, $vs_f);
                     }
                 }
             }
         }
     }
     if (!$vb_batch) {
         // hierarchy moves are not supported in batch mode
         if (is_array($va_fields_by_type['special'])) {
             foreach ($va_fields_by_type['special'] as $vs_placement_code => $vs_bundle) {
                 if ($vs_bundle !== 'hierarchy_location') {
                     continue;
                 }
                 $va_parent_tmp = explode("-", $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_new_parent_id", pString));
                 // Hierarchy browser sets new_parent_id param to "X" if user wants to extract item from hierarchy
                 $vn_parent_id = ($vn_parent_id = array_pop($va_parent_tmp)) == 'X' ? -1 : (int) $vn_parent_id;
                 if (sizeof($va_parent_tmp) > 0) {
                     $vs_parent_table = array_pop($va_parent_tmp);
                 } else {
                     $vs_parent_table = $this->tableName();
                 }
                 if ($this->getPrimaryKey() && $this->HIERARCHY_PARENT_ID_FLD && $vn_parent_id > 0) {
                     if ($vs_parent_table == $this->tableName()) {
                         $this->set($this->HIERARCHY_PARENT_ID_FLD, $vn_parent_id);
                     } else {
                         if ((bool) $this->getAppConfig()->get('ca_objects_x_collections_hierarchy_enabled') && $vs_parent_table == 'ca_collections' && $this->tableName() == 'ca_objects' && ($vs_coll_rel_type = $this->getAppConfig()->get('ca_objects_x_collections_hierarchy_relationship_type'))) {
                             // link object to collection
                             $this->removeRelationships('ca_collections', $vs_coll_rel_type);
                             $this->set($this->HIERARCHY_PARENT_ID_FLD, null);
                             $this->set($this->HIERARCHY_ID_FLD, $this->getPrimaryKey());
                             if (!$this->addRelationship('ca_collections', $vn_parent_id, $vs_coll_rel_type)) {
                                 $this->postError(2510, _t('Could not move object under collection: %1', join("; ", $this->getErrors())), "BundlableLabelableBaseModelWithAttributes->saveBundlesForScreen()");
                             }
                         }
                     }
                 } else {
                     if ($this->getPrimaryKey() && $this->HIERARCHY_PARENT_ID_FLD && $this->HIERARCHY_TYPE == __CA_HIER_TYPE_ADHOC_MONO__ && isset($_REQUEST["{$vs_placement_code}{$vs_form_prefix}_new_parent_id"]) && $vn_parent_id <= 0) {
                         $this->set($this->HIERARCHY_PARENT_ID_FLD, null);
                         $this->set($this->HIERARCHY_ID_FLD, $this->getPrimaryKey());
                         // Support for collection-object cross-table hierarchies
                         if ((bool) $this->getAppConfig()->get('ca_objects_x_collections_hierarchy_enabled') && $this->tableName() == 'ca_objects' && ($vs_coll_rel_type = $this->getAppConfig()->get('ca_objects_x_collections_hierarchy_relationship_type')) && $vn_parent_id == -1) {
                             // -1 = extract from hierarchy
                             $this->removeRelationships('ca_collections', $vs_coll_rel_type);
                         }
                     }
                 }
                 break;
             }
         }
     }
     //
     // Call processBundlesBeforeBaseModelSave() method in sub-class, if it is defined. The method is passed
     // a list of bundles, the form prefix, the current request and the options passed to saveBundlesForScreen() –
     // everything needed to perform custom processing using the incoming form content that is being saved.
     //
     // A processBundlesBeforeBaseModelSave() method is rarely needed, but can be handy when you need to do something model-specific
     // right before the basic database record is committed via insert() (for new records) or update() (for existing records).
     // For example, the media in ca_object_representations is set in a "special" bundle, which provides a specialized media upload UI. Unfortunately "special's"
     // are handled after the basic database record is saved via insert() or update(), while the actual media must be set prior to the save.
     // processBundlesBeforeBaseModelSave() allows special logic in the ca_object_representations model to be invoked to set the media before the insert() or update().
     // The "special" takes care of other functions after the insert()/update()
     //
     if (method_exists($this, "processBundlesBeforeBaseModelSave")) {
         $this->processBundlesBeforeBaseModelSave($va_bundles, $vs_form_prefix, $po_request, $pa_options);
     }
     $this->setMode(ACCESS_WRITE);
     $vb_is_insert = false;
     if ($this->getPrimaryKey()) {
         $this->update();
     } else {
         $this->insert();
         $vb_is_insert = true;
     }
     if ($this->numErrors() > 0) {
         $va_errors = array();
         foreach ($this->errors() as $o_e) {
             switch ($o_e->getErrorNumber()) {
                 case 2010:
                     $po_request->addActionErrors(array($o_e), 'hierarchy_location');
                     break;
                 case 795:
                     // field conflict
                     foreach ($this->getFieldConflicts() as $vs_conflict_field) {
                         $po_request->addActionError($o_e, $vs_conflict_field);
                     }
                     break;
                 case 1100:
                     if ($vs_idno_field = $this->getProperty('ID_NUMBERING_ID_FIELD')) {
                         $po_request->addActionError($o_e, $this->getProperty('ID_NUMBERING_ID_FIELD'));
                     }
                     break;
                 default:
                     $va_errors[] = $o_e;
                     break;
             }
         }
         $po_request->addActionErrors($va_errors);
         if ($vb_is_insert) {
             BaseModel::unsetChangeLogUnitID();
             if ($vb_we_set_transaction) {
                 $this->removeTransaction(false);
             }
             return false;
             // bail on insert error
         }
     }
     if (!$this->getPrimaryKey()) {
         BaseModel::unsetChangeLogUnitID();
         if ($vb_we_set_transaction) {
             $this->removeTransaction(false);
         }
         return false;
     }
     // bail if insert failed
     $this->clearErrors();
     //save reserved elements -  those with a saveElement method
     if (isset($reserved_elements) && is_array($reserved_elements)) {
         foreach ($reserved_elements as $res_element) {
             $res_element_id = $res_element->getPrimaryKey();
             $res_element_datatype = $res_element->get('datatype');
             $res_datatype = Attribute::getValueInstance($res_element_datatype);
             $res_datatype->saveElement($this, $res_element, $vs_form_prefix, $po_request);
         }
     }
     // save preferred labels
     if ($this->getProperty('LABEL_TABLE_NAME')) {
         $vb_check_for_dupe_labels = $this->_CONFIG->get('allow_duplicate_labels_for_' . $this->tableName()) ? false : true;
         $vb_error_inserting_pref_label = false;
         if (is_array($va_fields_by_type['preferred_label'])) {
             foreach ($va_fields_by_type['preferred_label'] as $vs_placement_code => $vs_f) {
                 if (!$vb_batch) {
                     // check for existing labels to update (or delete)
                     $va_preferred_labels = $this->getPreferredLabels(null, false);
                     foreach ($va_preferred_labels as $vn_item_id => $va_labels_by_locale) {
                         foreach ($va_labels_by_locale as $vn_locale_id => $va_label_list) {
                             foreach ($va_label_list as $va_label) {
                                 if ($vn_label_locale_id = $po_request->getParameter($vs_placement_code . $vs_form_prefix . '_Pref' . 'locale_id_' . $va_label['label_id'], pString)) {
                                     if (is_array($va_label_values = $this->getLabelUIValuesFromRequest($po_request, $vs_placement_code . $vs_form_prefix, $va_label['label_id'], true))) {
                                         if ($vb_check_for_dupe_labels && $this->checkForDupeLabel($vn_label_locale_id, $va_label_values)) {
                                             $this->postError(1125, _t('Value <em>%1</em> is already used and duplicates are not allowed', join("/", $va_label_values)), "BundlableLabelableBaseModelWithAttributes->saveBundlesForScreen()", $this->tableName() . '.preferred_labels');
                                             $po_request->addActionErrors($this->errors(), 'preferred_labels');
                                             continue;
                                         }
                                         $vn_label_type_id = $po_request->getParameter($vs_placement_code . $vs_form_prefix . '_Pref' . 'type_id_' . $va_label['label_id'], pInteger);
                                         $this->editLabel($va_label['label_id'], $va_label_values, $vn_label_locale_id, $vn_label_type_id, true);
                                         if ($this->numErrors()) {
                                             foreach ($this->errors() as $o_e) {
                                                 switch ($o_e->getErrorNumber()) {
                                                     case 795:
                                                         // field conflicts
                                                         $po_request->addActionError($o_e, 'preferred_labels');
                                                         break;
                                                     default:
                                                         $po_request->addActionError($o_e, $vs_f);
                                                         break;
                                                 }
                                             }
                                         }
                                     }
                                 } else {
                                     if ($po_request->getParameter($vs_placement_code . $vs_form_prefix . '_PrefLabel_' . $va_label['label_id'] . '_delete', pString)) {
                                         // delete
                                         $this->removeLabel($va_label['label_id']);
                                     }
                                 }
                             }
                         }
                     }
                 }
                 // check for new labels to add
                 foreach ($_REQUEST as $vs_key => $vs_value) {
                     if (!preg_match('/' . $vs_placement_code . $vs_form_prefix . '_Pref' . 'locale_id_new_([\\d]+)/', $vs_key, $va_matches)) {
                         continue;
                     }
                     if ($vb_batch) {
                         $vs_batch_mode = $po_request->getParameter($vs_placement_code . $vs_form_prefix . '_Pref_batch_mode', pString);
                         switch ($vs_batch_mode) {
                             case '_disabled_':
                                 // skip
                                 continue 2;
                                 break;
                             case '_replace_':
                                 // remove all existing preferred labels before trying to save
                                 $this->removeAllLabels(__CA_LABEL_TYPE_PREFERRED__);
                                 continue;
                             case '_delete_':
                                 // remove all existing preferred labels
                                 $this->removeAllLabels(__CA_LABEL_TYPE_PREFERRED__);
                                 continue 2;
                             case '_add_':
                                 break;
                         }
                     }
                     $vn_c = intval($va_matches[1]);
                     if ($vn_new_label_locale_id = $po_request->getParameter($vs_placement_code . $vs_form_prefix . '_Pref' . 'locale_id_new_' . $vn_c, pString)) {
                         if (is_array($va_label_values = $this->getLabelUIValuesFromRequest($po_request, $vs_placement_code . $vs_form_prefix, 'new_' . $vn_c, true))) {
                             // make sure we don't add multiple pref labels for one locale in batch mode
                             if ($vb_batch && $vs_batch_mode == '_add_') {
                                 // first remove [BLANK] labels for this locale if there are any, as we are about to add a new one
                                 $va_labels_for_this_locale = $this->getPreferredLabels(array($vn_new_label_locale_id));
                                 if (is_array($va_labels_for_this_locale)) {
                                     foreach ($va_labels_for_this_locale as $vn_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 (isset($va_label[$this->getLabelDisplayField()]) && $va_label[$this->getLabelDisplayField()] == '[' . _t('BLANK') . ']') {
                                                     $this->removeLabel($va_label['label_id']);
                                                 }
                                             }
                                         }
                                     }
                                 }
                                 // if there are non-[BLANK] labels for this locale, don't add this new one
                                 $va_labels_for_this_locale = $this->getPreferredLabels(array($vn_new_label_locale_id), true, array('forDisplay' => true));
                                 if (is_array($va_labels_for_this_locale) && sizeof($va_labels_for_this_locale) > 0) {
                                     $this->postError(1125, _t('A preferred label for this locale already exists. Only one preferred label per locale is allowed.'), "BundlableLabelableBaseModelWithAttributes->saveBundlesForScreen()", $this->tableName() . '.preferred_labels');
                                     $po_request->addActionErrors($this->errors(), $vs_f);
                                     $vb_error_inserting_pref_label = true;
                                     continue;
                                 }
                             }
                             if ($vb_check_for_dupe_labels && $this->checkForDupeLabel($vn_new_label_locale_id, $va_label_values)) {
                                 $this->postError(1125, _t('Value <em>%1</em> is already used and duplicates are not allowed', join("/", $va_label_values)), "BundlableLabelableBaseModelWithAttributes->saveBundlesForScreen()", $this->tableName() . '.preferred_labels');
                                 $po_request->addActionErrors($this->errors(), 'preferred_labels');
                                 $vb_error_inserting_pref_label = true;
                                 continue;
                             }
                             $vn_label_type_id = $po_request->getParameter($vs_placement_code . $vs_form_prefix . '_Pref' . 'type_id_new_' . $vn_c, pInteger);
                             $this->addLabel($va_label_values, $vn_new_label_locale_id, $vn_label_type_id, true);
                             if ($this->numErrors()) {
                                 $po_request->addActionErrors($this->errors(), $vs_f);
                                 $vb_error_inserting_pref_label = true;
                             }
                         }
                     }
                 }
             }
         }
     }
     // Add default label if needed (ie. if the user has failed to set at least one label or if they have deleted all existing labels)
     // This ensures at least one label is present for the record. If no labels are present then the
     // record may not be found in queries
     if ($this->getProperty('LABEL_TABLE_NAME')) {
         if ($vb_error_inserting_pref_label || !$this->addDefaultLabel($vn_new_label_locale_id)) {
             if (!$vb_error_inserting_pref_label) {
                 $po_request->addActionErrors($this->errors(), 'preferred_labels');
             }
             if ($vb_we_set_transaction) {
                 $this->removeTransaction(false);
             }
             if ($vb_is_insert) {
                 $this->_FIELD_VALUES[$this->primaryKey()] = null;
                 // clear primary key, which doesn't actually exist since we rolled back the transaction
                 foreach ($va_inserted_attributes_by_element as $vn_element_id => $va_failed_inserts) {
                     // set attributes as "failed" (but with no error messages) so they stay set
                     $this->setFailedAttributeInserts($vn_element_id, $va_failed_inserts);
                 }
             }
             return false;
         }
     }
     unset($va_inserted_attributes_by_element);
     // save non-preferred labels
     if ($this->getProperty('LABEL_TABLE_NAME') && isset($va_fields_by_type['nonpreferred_label']) && is_array($va_fields_by_type['nonpreferred_label'])) {
         if (!$vb_batch) {
             foreach ($va_fields_by_type['nonpreferred_label'] as $vs_placement_code => $vs_f) {
                 // check for existing labels to update (or delete)
                 $va_nonpreferred_labels = $this->getNonPreferredLabels(null, false);
                 foreach ($va_nonpreferred_labels as $vn_item_id => $va_labels_by_locale) {
                     foreach ($va_labels_by_locale as $vn_locale_id => $va_label_list) {
                         foreach ($va_label_list as $va_label) {
                             if ($vn_label_locale_id = $po_request->getParameter($vs_placement_code . $vs_form_prefix . '_NPref' . 'locale_id_' . $va_label['label_id'], pString)) {
                                 if (is_array($va_label_values = $this->getLabelUIValuesFromRequest($po_request, $vs_placement_code . $vs_form_prefix, $va_label['label_id'], false))) {
                                     $vn_label_type_id = $po_request->getParameter($vs_placement_code . $vs_form_prefix . '_NPref' . 'type_id_' . $va_label['label_id'], pInteger);
                                     $this->editLabel($va_label['label_id'], $va_label_values, $vn_label_locale_id, $vn_label_type_id, false);
                                     if ($this->numErrors()) {
                                         foreach ($this->errors() as $o_e) {
                                             switch ($o_e->getErrorNumber()) {
                                                 case 795:
                                                     // field conflicts
                                                     $po_request->addActionError($o_e, 'nonpreferred_labels');
                                                     break;
                                                 default:
                                                     $po_request->addActionError($o_e, $vs_f);
                                                     break;
                                             }
                                         }
                                     }
                                 }
                             } else {
                                 if ($po_request->getParameter($vs_placement_code . $vs_form_prefix . '_NPrefLabel_' . $va_label['label_id'] . '_delete', pString)) {
                                     // delete
                                     $this->removeLabel($va_label['label_id']);
                                 }
                             }
                         }
                     }
                 }
             }
         }
         // check for new labels to add
         foreach ($va_fields_by_type['nonpreferred_label'] as $vs_placement_code => $vs_f) {
             if ($vb_batch) {
                 $vs_batch_mode = $po_request->getParameter($vs_placement_code . $vs_form_prefix . '_NPref_batch_mode', pString);
                 switch ($vs_batch_mode) {
                     case '_disabled_':
                         // skip
                         continue 2;
                         break;
                     case '_add_':
                         // just try to add attribute as in normal non-batch save
                         // noop
                         break;
                     case '_replace_':
                         // remove all existing nonpreferred labels before trying to save
                         $this->removeAllLabels(__CA_LABEL_TYPE_NONPREFERRED__);
                         continue;
                     case '_delete_':
                         // remove all existing nonpreferred labels
                         $this->removeAllLabels(__CA_LABEL_TYPE_NONPREFERRED__);
                         continue 2;
                         break;
                 }
             }
             foreach ($_REQUEST as $vs_key => $vs_value) {
                 if (!preg_match('/^' . $vs_placement_code . $vs_form_prefix . '_NPref' . 'locale_id_new_([\\d]+)/', $vs_key, $va_matches)) {
                     continue;
                 }
                 $vn_c = intval($va_matches[1]);
                 if ($vn_new_label_locale_id = $po_request->getParameter($vs_placement_code . $vs_form_prefix . '_NPref' . 'locale_id_new_' . $vn_c, pString)) {
                     if (is_array($va_label_values = $this->getLabelUIValuesFromRequest($po_request, $vs_placement_code . $vs_form_prefix, 'new_' . $vn_c, false))) {
                         $vn_new_label_type_id = $po_request->getParameter($vs_placement_code . $vs_form_prefix . '_NPref' . 'type_id_new_' . $vn_c, pInteger);
                         $this->addLabel($va_label_values, $vn_new_label_locale_id, $vn_new_label_type_id, false);
                         if ($this->numErrors()) {
                             $po_request->addActionErrors($this->errors(), $vs_f);
                         }
                     }
                 }
             }
         }
     }
     // save data in related tables
     if (isset($va_fields_by_type['related_table']) && is_array($va_fields_by_type['related_table'])) {
         foreach ($va_fields_by_type['related_table'] as $vs_placement_code => $vs_f) {
             $vn_table_num = $this->_DATAMODEL->getTableNum($vs_f);
             // get settings
             $va_bundle_settings = array();
             foreach ($va_bundles as $va_bundle_info) {
                 if ($va_bundle_info['placement_code'] == $vs_placement_code) {
                     $va_bundle_settings = $va_bundle_info['settings'];
                     break;
                 }
             }
             switch ($vs_f) {
                 # -------------------------------------
                 case 'ca_object_representations':
                     // check for existing representations to update (or delete)
                     $vs_prefix_stub = $vs_placement_code . $vs_form_prefix . '_';
                     $vb_allow_fetching_of_urls = (bool) $this->_CONFIG->get('allow_fetching_of_media_from_remote_urls');
                     $va_rep_ids_sorted = $va_rep_sort_order = explode(';', $po_request->getParameter($vs_prefix_stub . 'ObjectRepresentationBundleList', pString));
                     sort($va_rep_ids_sorted, SORT_NUMERIC);
                     $va_reps = $this->getRepresentations();
                     if (!$vb_batch && is_array($va_reps)) {
                         foreach ($va_reps as $vn_i => $va_rep) {
                             $this->clearErrors();
                             if (strlen($po_request->getParameter($vs_prefix_stub . 'access_' . $va_rep['representation_id'], pInteger)) > 0) {
                                 if ($vb_allow_fetching_of_urls && ($vs_path = $_REQUEST[$vs_prefix_stub . 'media_url_' . $va_rep['representation_id']])) {
                                     $va_tmp = explode('/', $vs_path);
                                     $vs_original_name = array_pop($va_tmp);
                                 } else {
                                     $vs_path = $_FILES[$vs_prefix_stub . 'media_' . $va_rep['representation_id']]['tmp_name'];
                                     $vs_original_name = $_FILES[$vs_prefix_stub . 'media_' . $va_rep['representation_id']]['name'];
                                 }
                                 $vn_is_primary = $po_request->getParameter($vs_prefix_stub . 'is_primary_' . $va_rep['representation_id'], pString) != '' ? $po_request->getParameter($vs_prefix_stub . 'is_primary_' . $va_rep['representation_id'], pInteger) : null;
                                 $vn_locale_id = $po_request->getParameter($vs_prefix_stub . 'locale_id_' . $va_rep['representation_id'], pInteger);
                                 $vs_idno = $po_request->getParameter($vs_prefix_stub . 'idno_' . $va_rep['representation_id'], pString);
                                 $vn_access = $po_request->getParameter($vs_prefix_stub . 'access_' . $va_rep['representation_id'], pInteger);
                                 $vn_status = $po_request->getParameter($vs_prefix_stub . 'status_' . $va_rep['representation_id'], pInteger);
                                 $vs_rep_label = trim($po_request->getParameter($vs_prefix_stub . 'rep_label_' . $va_rep['representation_id'], pString));
                                 //$vn_rep_type_id = $po_request->getParameter($vs_prefix_stub.'rep_type_id'.$va_rep['representation_id'], pInteger);
                                 // Get user-specified center point (images only)
                                 $vn_center_x = $po_request->getParameter($vs_prefix_stub . 'center_x_' . $va_rep['representation_id'], pString);
                                 $vn_center_y = $po_request->getParameter($vs_prefix_stub . 'center_y_' . $va_rep['representation_id'], pString);
                                 $vn_rank = null;
                                 if (($vn_rank_index = array_search($va_rep['representation_id'], $va_rep_sort_order)) !== false) {
                                     $vn_rank = $va_rep_ids_sorted[$vn_rank_index];
                                 }
                                 $this->editRepresentation($va_rep['representation_id'], $vs_path, $vn_locale_id, $vn_status, $vn_access, $vn_is_primary, array('idno' => $vs_idno), array('original_filename' => $vs_original_name, 'rank' => $vn_rank, 'centerX' => $vn_center_x, 'centerY' => $vn_center_y));
                                 if ($this->numErrors()) {
                                     //$po_request->addActionErrors($this->errors(), $vs_f, $va_rep['representation_id']);
                                     foreach ($this->errors() as $o_e) {
                                         switch ($o_e->getErrorNumber()) {
                                             case 795:
                                                 // field conflicts
                                                 $po_request->addActionError($o_e, $vs_f, $va_rep['representation_id']);
                                                 break;
                                             default:
                                                 $po_request->addActionError($o_e, $vs_f, $va_rep['representation_id']);
                                                 break;
                                         }
                                     }
                                 }
                                 if ($vs_rep_label) {
                                     //
                                     // Set representation label
                                     //
                                     $t_rep = new ca_object_representations();
                                     if ($this->inTransaction()) {
                                         $t_rep->setTransaction($this->getTransaction());
                                     }
                                     global $g_ui_locale_id;
                                     if ($t_rep->load($va_rep['representation_id'])) {
                                         $t_rep->setMode(ACCESS_WRITE);
                                         $t_rep->replaceLabel(array('name' => $vs_rep_label), $g_ui_locale_id, null, true);
                                         if ($t_rep->numErrors()) {
                                             $po_request->addActionErrors($t_rep->errors(), $vs_f, $va_rep['representation_id']);
                                         }
                                     }
                                 }
                             } else {
                                 // is it a delete key?
                                 $this->clearErrors();
                                 if ($po_request->getParameter($vs_prefix_stub . $va_rep['representation_id'] . '_delete', pInteger) > 0) {
                                     // delete!
                                     $this->removeRepresentation($va_rep['representation_id']);
                                     if ($this->numErrors()) {
                                         $po_request->addActionErrors($this->errors(), $vs_f, $va_rep['representation_id']);
                                     }
                                 }
                             }
                         }
                     }
                     if ($vb_batch) {
                         $vs_batch_mode = $_REQUEST[$vs_prefix_stub . 'batch_mode'];
                         if ($vs_batch_mode == '_disabled_') {
                             break;
                         }
                         if ($vs_batch_mode == '_replace_') {
                             $this->removeAllRepresentations();
                         }
                         if ($vs_batch_mode == '_delete_') {
                             $this->removeAllRepresentations();
                             break;
                         }
                     }
                     // check for new representations to add
                     $va_file_list = $_FILES;
                     foreach ($_REQUEST as $vs_key => $vs_value) {
                         if (!preg_match('/^' . $vs_prefix_stub . 'media_url_new_([\\d]+)$/', $vs_key, $va_matches)) {
                             continue;
                         }
                         $va_file_list[$vs_key] = array('url' => $vs_value);
                     }
                     foreach ($va_file_list as $vs_key => $va_values) {
                         $this->clearErrors();
                         if (!preg_match('/^' . $vs_prefix_stub . 'media_new_([\\d]+)$/', $vs_key, $va_matches) && ($vb_allow_fetching_of_urls && !preg_match('/^' . $vs_prefix_stub . 'media_url_new_([\\d]+)$/', $vs_key, $va_matches) || !$vb_allow_fetching_of_urls)) {
                             continue;
                         }
                         if ($vs_upload_type = $po_request->getParameter($vs_prefix_stub . 'upload_typenew_' . $va_matches[1], pString)) {
                             $po_request->user->setVar('defaultRepresentationUploadType', $vs_upload_type);
                         }
                         $vn_type_id = $po_request->getParameter($vs_prefix_stub . 'type_id_new_' . $va_matches[1], pInteger);
                         if ($vn_existing_rep_id = $po_request->getParameter($vs_prefix_stub . 'idnew_' . $va_matches[1], pInteger)) {
                             $this->addRelationship('ca_object_representations', $vn_existing_rep_id, $vn_type_id);
                         } else {
                             if ($vb_allow_fetching_of_urls && ($vs_path = $va_values['url'])) {
                                 $va_tmp = explode('/', $vs_path);
                                 $vs_original_name = array_pop($va_tmp);
                             } else {
                                 $vs_path = $va_values['tmp_name'];
                                 $vs_original_name = $va_values['name'];
                             }
                             if (!$vs_path) {
                                 continue;
                             }
                             $vn_rep_type_id = $po_request->getParameter($vs_prefix_stub . 'rep_type_id_new_' . $va_matches[1], pInteger);
                             if (!$vn_rep_type_id && !($vn_rep_type_id = caGetDefaultItemID('object_representation_types'))) {
                                 require_once __CA_MODELS_DIR__ . '/ca_lists.php';
                                 $t_list = new ca_lists();
                                 if (is_array($va_rep_type_ids = $t_list->getItemsForList('object_representation_types', array('idsOnly' => true, 'enabledOnly' => true)))) {
                                     $vn_rep_type_id = array_shift($va_rep_type_ids);
                                 }
                             }
                             if (is_array($pa_options['existingRepresentationMap']) && isset($pa_options['existingRepresentationMap'][$vs_path]) && $pa_options['existingRepresentationMap'][$vs_path]) {
                                 $this->addRelationship('ca_object_representations', $pa_options['existingRepresentationMap'][$vs_path], $vn_type_id);
                                 break;
                             }
                             $vs_rep_label = trim($po_request->getParameter($vs_prefix_stub . 'rep_label_new_' . $va_matches[1], pString));
                             $vn_locale_id = $po_request->getParameter($vs_prefix_stub . 'locale_id_new_' . $va_matches[1], pInteger);
                             $vs_idno = $po_request->getParameter($vs_prefix_stub . 'idno_new_' . $va_matches[1], pString);
                             $vn_status = $po_request->getParameter($vs_prefix_stub . 'status_new_' . $va_matches[1], pInteger);
                             $vn_access = $po_request->getParameter($vs_prefix_stub . 'access_new_' . $va_matches[1], pInteger);
                             $vn_is_primary = $po_request->getParameter($vs_prefix_stub . 'is_primary_new_' . $va_matches[1], pInteger);
                             // Get user-specified center point (images only)
                             $vn_center_x = $po_request->getParameter($vs_prefix_stub . 'center_x_new_' . $va_matches[1], pString);
                             $vn_center_y = $po_request->getParameter($vs_prefix_stub . 'center_y_new_' . $va_matches[1], pString);
                             $t_rep = $this->addRepresentation($vs_path, $vn_rep_type_id, $vn_locale_id, $vn_status, $vn_access, $vn_is_primary, array('name' => $vs_rep_label, 'idno' => $vs_idno), array('original_filename' => $vs_original_name, 'returnRepresentation' => true, 'centerX' => $vn_center_x, 'centerY' => $vn_center_y, 'type_id' => $vn_type_id));
                             // $vn_type_id = *relationship* type_id (as opposed to representation type)
                             if ($this->numErrors()) {
                                 $po_request->addActionErrors($this->errors(), $vs_f, 'new_' . $va_matches[1]);
                             } else {
                                 if ($t_rep && is_array($pa_options['existingRepresentationMap'])) {
                                     $pa_options['existingRepresentationMap'][$vs_path] = $t_rep->getPrimaryKey();
                                 }
                             }
                         }
                     }
                     break;
                     # -------------------------------------
                 # -------------------------------------
                 case 'ca_entities':
                 case 'ca_places':
                 case 'ca_objects':
                 case 'ca_collections':
                 case 'ca_occurrences':
                 case 'ca_list_items':
                 case 'ca_object_lots':
                 case 'ca_storage_locations':
                 case 'ca_loans':
                 case 'ca_movements':
                 case 'ca_tour_stops':
                     $this->_processRelated($po_request, $vs_f, $vs_form_prefix, $vs_placement_code, array('batch' => $vb_batch, 'settings' => $va_bundle_settings));
                     break;
                     # -------------------------------------
                 # -------------------------------------
                 case 'ca_representation_annotations':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     $this->_processRepresentationAnnotations($po_request, $vs_form_prefix, $vs_placement_code);
                     break;
                     # -------------------------------------
             }
         }
     }
     // save data for "specials"
     if (isset($va_fields_by_type['special']) && is_array($va_fields_by_type['special'])) {
         foreach ($va_fields_by_type['special'] as $vs_placement_code => $vs_f) {
             // get settings
             $va_bundle_settings = array();
             foreach ($va_bundles as $va_bundle_info) {
                 if ('P' . $va_bundle_info['placement_id'] == $vs_placement_code) {
                     $va_bundle_settings = $va_bundle_info['settings'];
                     break;
                 }
             }
             switch ($vs_f) {
                 # -------------------------------------
                 // This bundle is only available when editing objects of type ca_representation_annotations
                 case 'ca_representation_annotation_properties':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     if (!$this->useInEditor()) {
                         break;
                     }
                     foreach ($this->getPropertyList() as $vs_property) {
                         $this->setPropertyValue($vs_property, $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}{$vs_property}", pString));
                     }
                     if (!$this->validatePropertyValues()) {
                         $po_request->addActionErrors($this->errors(), 'ca_representation_annotation_properties', 'general');
                     }
                     $this->update();
                     break;
                     # -------------------------------------
                     // This bundle is only available for types which support set membership
                 # -------------------------------------
                 // This bundle is only available for types which support set membership
                 case 'ca_sets':
                     // check for existing labels to delete (no updating supported)
                     require_once __CA_MODELS_DIR__ . '/ca_sets.php';
                     require_once __CA_MODELS_DIR__ . '/ca_set_items.php';
                     $t_set = new ca_sets();
                     if (!$vb_batch) {
                         $va_sets = caExtractValuesByUserLocale($t_set->getSetsForItem($this->tableNum(), $this->getPrimaryKey(), array('user_id' => $po_request->getUserID())));
                         foreach ($va_sets as $vn_set_id => $va_set_info) {
                             $vn_item_id = $va_set_info['item_id'];
                             if ($po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_set_id_{$vn_item_id}_delete", pString)) {
                                 // delete
                                 $t_set->load($va_set_info['set_id']);
                                 $t_set->removeItem($this->getPrimaryKey(), $po_request->getUserID());
                                 // remove *all* instances of the item in the set, not just the specified id
                                 if ($t_set->numErrors()) {
                                     $po_request->addActionErrors($t_set->errors(), $vs_f);
                                 }
                             }
                         }
                     }
                     if ($vb_batch) {
                         $vs_batch_mode = $_REQUEST["{$vs_placement_code}{$vs_form_prefix}_batch_mode"];
                         if ($vs_batch_mode == '_disabled_') {
                             break;
                         }
                         if ($vs_batch_mode == '_replace_') {
                             $t_set->removeItemFromAllSets($this->tableNum(), $this->getPrimaryKey());
                         }
                         if ($vs_batch_mode == '_delete_') {
                             $t_set->removeItemFromAllSets($this->tableNum(), $this->getPrimaryKey());
                             break;
                         }
                     }
                     foreach ($_REQUEST as $vs_key => $vs_value) {
                         if (!preg_match("/{$vs_placement_code}{$vs_form_prefix}_set_id_new_([\\d]+)/", $vs_key, $va_matches)) {
                             continue;
                         }
                         $vn_c = intval($va_matches[1]);
                         if ($vn_new_set_id = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_set_id_new_{$vn_c}", pString)) {
                             $t_set->load($vn_new_set_id);
                             $t_set->addItem($this->getPrimaryKey(), null, $po_request->getUserID());
                             if ($t_set->numErrors()) {
                                 $po_request->addActionErrors($t_set->errors(), $vs_f);
                             }
                         }
                     }
                     break;
                     # -------------------------------------
                     // This bundle is only available for types which support set membership
                 # -------------------------------------
                 // This bundle is only available for types which support set membership
                 case 'ca_set_items':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     // check for existing labels to delete (no updating supported)
                     require_once __CA_MODELS_DIR__ . '/ca_sets.php';
                     require_once __CA_MODELS_DIR__ . '/ca_set_items.php';
                     $va_rids = explode(';', $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}setRowIDList", pString));
                     $this->reorderItems($va_rids, array('user_id' => $po_request->getUserID(), 'treatRowIDsAsRIDs' => true, 'deleteExcludedItems' => true));
                     break;
                     # -------------------------------------
                     // This bundle is only available for ca_search_forms
                 # -------------------------------------
                 // This bundle is only available for ca_search_forms
                 case 'ca_search_form_elements':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     // save settings
                     $va_settings = $this->getAvailableSettings();
                     foreach ($va_settings as $vs_setting => $va_setting_info) {
                         if (isset($_REQUEST['setting_' . $vs_setting])) {
                             $vs_setting_val = $po_request->getParameter('setting_' . $vs_setting, pString);
                             $this->setSetting($vs_setting, $vs_setting_val);
                             $this->update();
                         }
                     }
                     break;
                     # -------------------------------------
                     // This bundle is only available for ca_bundle_displays
                 # -------------------------------------
                 // This bundle is only available for ca_bundle_displays
                 case 'ca_bundle_display_placements':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     $this->savePlacementsFromHTMLForm($po_request, $vs_form_prefix, $vs_placement_code);
                     break;
                     # -------------------------------------
                     // This bundle is only available for ca_bundle_displays
                 # -------------------------------------
                 // This bundle is only available for ca_bundle_displays
                 case 'ca_bundle_display_type_restrictions':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     $this->saveTypeRestrictionsFromHTMLForm($po_request, $vs_form_prefix, $vs_placement_code);
                     break;
                     # -------------------------------------
                     // This bundle is only available for ca_search_forms
                 # -------------------------------------
                 // This bundle is only available for ca_search_forms
                 case 'ca_search_form_placements':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     $this->savePlacementsFromHTMLForm($po_request, $vs_form_prefix, $vs_placement_code);
                     break;
                     # -------------------------------------
                     // This bundle is only available for ca_editor_ui
                 # -------------------------------------
                 // This bundle is only available for ca_editor_ui
                 case 'ca_editor_ui_screens':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     global $g_ui_locale_id;
                     require_once __CA_MODELS_DIR__ . '/ca_editor_ui_screens.php';
                     $va_screen_ids = explode(';', $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_ScreenBundleList", pString));
                     foreach ($_REQUEST as $vs_key => $vs_val) {
                         if (is_array($vs_val)) {
                             continue;
                         }
                         if (!($vs_val = trim($vs_val))) {
                             continue;
                         }
                         if (preg_match("!^{$vs_placement_code}{$vs_form_prefix}_name_new_([\\d]+)\$!", $vs_key, $va_matches)) {
                             if (!($t_screen = $this->addScreen($vs_val, $g_ui_locale_id, 'screen_' . $this->getPrimaryKey() . '_' . $va_matches[1]))) {
                                 break;
                             }
                             if ($vn_fkey = array_search("new_" . $va_matches[1], $va_screen_ids)) {
                                 $va_screen_ids[$vn_fkey] = $t_screen->getPrimaryKey();
                             } else {
                                 $va_screen_ids[] = $t_screen->getPrimaryKey();
                             }
                             continue;
                         }
                         if (preg_match("!^{$vs_placement_code}{$vs_form_prefix}_([\\d]+)_delete\$!", $vs_key, $va_matches)) {
                             $this->removeScreen($va_matches[1]);
                             if ($vn_fkey = array_search($va_matches[1], $va_screen_ids)) {
                                 unset($va_screen_ids[$vn_fkey]);
                             }
                         }
                     }
                     $this->reorderScreens($va_screen_ids);
                     break;
                     # -------------------------------------
                     // This bundle is only available for ca_editor_ui_screens
                 # -------------------------------------
                 // This bundle is only available for ca_editor_ui_screens
                 case 'ca_editor_ui_bundle_placements':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     $this->savePlacementsFromHTMLForm($po_request, $vs_form_prefix, $vs_placement_code);
                     break;
                     # -------------------------------------
                     // This bundle is only available for ca_editor_uis
                 # -------------------------------------
                 // This bundle is only available for ca_editor_uis
                 case 'ca_editor_ui_type_restrictions':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     $this->saveTypeRestrictionsFromHTMLForm($po_request, $vs_form_prefix, $vs_placement_code);
                     break;
                     # -------------------------------------
                     // This bundle is only available for ca_editor_ui_screens
                 # -------------------------------------
                 // This bundle is only available for ca_editor_ui_screens
                 case 'ca_editor_ui_screen_type_restrictions':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     $this->saveTypeRestrictionsFromHTMLForm($po_request, $vs_form_prefix, $vs_placement_code);
                     break;
                     # -------------------------------------
                     // This bundle is only available for ca_tours
                 # -------------------------------------
                 // This bundle is only available for ca_tours
                 case 'ca_tour_stops_list':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     global $g_ui_locale_id;
                     require_once __CA_MODELS_DIR__ . '/ca_tour_stops.php';
                     $va_stop_ids = explode(';', $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_StopBundleList", pString));
                     foreach ($_REQUEST as $vs_key => $vs_val) {
                         if (!($vs_val = trim($vs_val))) {
                             continue;
                         }
                         if (preg_match("!^{$vs_placement_code}{$vs_form_prefix}_name_new_([\\d]+)\$!", $vs_key, $va_matches)) {
                             $vn_type_id = $_REQUEST["{$vs_placement_code}{$vs_form_prefix}_type_id_new_" . $va_matches[1]];
                             if (!($t_stop = $this->addStop($vs_val, $vn_type_id, $g_ui_locale_id, mb_substr(preg_replace('![^A-Za-z0-9_]+!', '_', $vs_val), 0, 255)))) {
                                 break;
                             }
                             if ($vn_fkey = array_search("new_" . $va_matches[1], $va_stop_ids)) {
                                 $va_stop_ids[$vn_fkey] = $t_stop->getPrimaryKey();
                             } else {
                                 $va_stop_ids[] = $t_stop->getPrimaryKey();
                             }
                             continue;
                         }
                         if (preg_match("!^{$vs_placement_code}{$vs_form_prefix}_([\\d]+)_delete\$!", $vs_key, $va_matches)) {
                             $this->removeStop($va_matches[1]);
                             if ($vn_fkey = array_search($va_matches[1], $va_stop_ids)) {
                                 unset($va_stop_ids[$vn_fkey]);
                             }
                         }
                     }
                     $this->reorderStops($va_stop_ids);
                     break;
                     # -------------------------------------
                 # -------------------------------------
                 case 'ca_user_groups':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     if (!$po_request->user->canDoAction('is_administrator') && $po_request->getUserID() != $this->get('user_id')) {
                         break;
                     }
                     // don't save if user is not owner
                     require_once __CA_MODELS_DIR__ . '/ca_user_groups.php';
                     $va_groups_to_set = $va_group_effective_dates = array();
                     foreach ($_REQUEST as $vs_key => $vs_val) {
                         if (preg_match("!^{$vs_placement_code}{$vs_form_prefix}_id(.*)\$!", $vs_key, $va_matches)) {
                             $vs_effective_date = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_effective_date_" . $va_matches[1], pString);
                             $vn_group_id = (int) $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_id" . $va_matches[1], pInteger);
                             $vn_access = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_access_" . $va_matches[1], pInteger);
                             if ($vn_access > 0) {
                                 $va_groups_to_set[$vn_group_id] = $vn_access;
                                 $va_group_effective_dates[$vn_group_id] = $vs_effective_date;
                             }
                         }
                     }
                     $this->setUserGroups($va_groups_to_set, $va_group_effective_dates, array('user_id' => $po_request->getUserID()));
                     break;
                     # -------------------------------------
                 # -------------------------------------
                 case 'ca_users':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     if (!$po_request->user->canDoAction('is_administrator') && $po_request->getUserID() != $this->get('user_id')) {
                         break;
                     }
                     // don't save if user is not owner
                     require_once __CA_MODELS_DIR__ . '/ca_users.php';
                     $va_users_to_set = $va_user_effective_dates = array();
                     foreach ($_REQUEST as $vs_key => $vs_val) {
                         if (preg_match("!^{$vs_placement_code}{$vs_form_prefix}_id(.*)\$!", $vs_key, $va_matches)) {
                             $vs_effective_date = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_effective_date_" . $va_matches[1], pString);
                             $vn_user_id = (int) $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_id" . $va_matches[1], pInteger);
                             $vn_access = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_access_" . $va_matches[1], pInteger);
                             if ($vn_access > 0) {
                                 $va_users_to_set[$vn_user_id] = $vn_access;
                                 $va_user_effective_dates[$vn_user_id] = $vs_effective_date;
                             }
                         }
                     }
                     $this->setUsers($va_users_to_set, $va_user_effective_dates);
                     break;
                     # -------------------------------------
                 # -------------------------------------
                 case 'settings':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     $this->setSettingsFromHTMLForm($po_request, array('id' => $vs_form_prefix . '_', 'placement_code' => $vs_placement_code));
                     break;
                     # -------------------------------
                     // This bundle is only available when editing objects of type ca_object_representations
                 # -------------------------------
                 // This bundle is only available when editing objects of type ca_object_representations
                 case 'ca_object_representations_media_display':
                     if ($vb_batch) {
                         break;
                     }
                     // not supported in batch mode
                     $va_versions_to_process = null;
                     if ($vb_use_options = (bool) $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_derivative_options_selector", pInteger)) {
                         // update only specified versions
                         $va_versions_to_process = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_set_versions", pArray);
                     }
                     if (!is_array($va_versions_to_process) || !sizeof($va_versions_to_process)) {
                         $va_versions_to_process = array('_all');
                     }
                     if ($vb_use_options && $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_derivative_options_mode", pString) == 'timecode') {
                         // timecode
                         if (!(string) ($vs_timecode = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_derivative_options_mode_timecode_value", pString))) {
                             $vs_timecode = "1s";
                         }
                         //
                         $o_media = new Media();
                         if ($o_media->read($this->getMediaPath('media', 'original'))) {
                             $va_files = $o_media->writePreviews(array('force' => true, 'outputDirectory' => $this->_CONFIG->get("taskqueue_tmp_directory"), 'minNumberOfFrames' => 1, 'maxNumberOfFrames' => 1, 'startAtTime' => $vs_timecode, 'endAtTime' => $vs_timecode, 'width' => 720, 'height' => 540));
                             if (sizeof($va_files)) {
                                 $this->set('media', array_shift($va_files));
                             }
                         }
                     } else {
                         if ($vb_use_options && $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_derivative_options_mode", pString) == 'page') {
                             if (!(int) ($vn_page = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_derivative_options_mode_page_value", pInteger))) {
                                 $vn_page = 1;
                             }
                             //
                             $o_media = new Media();
                             if ($o_media->read($this->getMediaPath('media', 'original'))) {
                                 $va_files = $o_media->writePreviews(array('force' => true, 'outputDirectory' => $this->_CONFIG->get("taskqueue_tmp_directory"), 'numberOfPages' => 1, 'startAtPage' => $vn_page, 'width' => 2048, 'height' => 2048));
                                 if (sizeof($va_files)) {
                                     $this->set('media', array_shift($va_files));
                                 }
                             }
                         } else {
                             // process file as new upload
                             $vs_key = "{$vs_placement_code}{$vs_form_prefix}_url";
                             if (($vs_media_url = trim($po_request->getParameter($vs_key, pString))) && isURL($vs_media_url)) {
                                 $this->set('media', $vs_media_url);
                             } else {
                                 $vs_key = "{$vs_placement_code}{$vs_form_prefix}_media";
                                 if (isset($_FILES[$vs_key])) {
                                     $this->set('media', $_FILES[$vs_key]['tmp_name'], array('original_filename' => $_FILES[$vs_key]['name']));
                                 }
                             }
                         }
                     }
                     if ($this->changed('media')) {
                         $this->update($vs_version != '_all' ? array('updateOnlyMediaVersions' => $va_versions_to_process) : array());
                         if ($this->numErrors()) {
                             $po_request->addActionErrors($this->errors(), 'ca_object_representations_media_display', 'general');
                         }
                     }
                     break;
                     # -------------------------------
                     // This bundle is only available when editing objects of type ca_object_representations
                 # -------------------------------
                 // This bundle is only available when editing objects of type ca_object_representations
                 case 'ca_object_representation_captions':
                     if ($vb_batch) {
                         return null;
                     }
                     // not supported in batch mode
                     $va_users_to_set = array();
                     foreach ($_REQUEST as $vs_key => $vs_val) {
                         if (preg_match("!^{$vs_placement_code}{$vs_form_prefix}_locale_id(.*)\$!", $vs_key, $va_matches)) {
                             $vn_locale_id = (int) $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_locale_id" . $va_matches[1], pInteger);
                             $this->addCaptionFile($_FILES["{$vs_placement_code}{$vs_form_prefix}_caption_file" . $va_matches[1]]['tmp_name'], $vn_locale_id, array('originalFilename' => $_FILES["{$vs_placement_code}{$vs_form_prefix}_captions_caption_file" . $va_matches[1]]['name']));
                         } else {
                             // any to delete?
                             if (preg_match("!^{$vs_placement_code}{$vs_form_prefix}_([\\d]+)_delete\$!", $vs_key, $va_matches)) {
                                 $this->removeCaptionFile((int) $va_matches[1]);
                             }
                         }
                     }
                     break;
                     # -------------------------------
                     // This bundle is only available for relationships that include an object on one end
                 # -------------------------------
                 // This bundle is only available for relationships that include an object on one end
                 case 'ca_object_representation_chooser':
                     if ($vb_batch) {
                         return null;
                     }
                     // not supported in batch mode
                     if (!is_array($va_rep_ids = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}", pArray))) {
                         $va_rep_ids = array();
                     }
                     if ($vs_element_code = caGetOption(array('elementCode', 'element_code'), $va_bundle_settings, null)) {
                         if (!is_array($va_current_rep_ids = $this->get($this->tableName() . "." . $vs_element_code, array('returnAsArray' => true, 'idsOnly' => true)))) {
                             $va_current_rep_ids = $va_current_rep_id_with_structure = array();
                         } else {
                             $va_current_rep_id_with_structure = $this->get($this->tableName() . "." . $vs_element_code, array('returnWithStructure' => true, 'idsOnly' => true));
                         }
                         $va_rep_to_attr_id = array();
                         foreach ($va_rep_ids as $vn_rep_id) {
                             if (in_array($vn_rep_id, $va_current_rep_ids)) {
                                 continue;
                             }
                             $this->addAttribute(array($vs_element_code => $vn_rep_id), $vs_element_code);
                         }
                         foreach ($va_current_rep_id_with_structure as $vn_id => $va_vals_by_attr_id) {
                             foreach ($va_vals_by_attr_id as $vn_attribute_id => $va_val) {
                                 if (!in_array($va_val[$vs_element_code], $va_rep_ids)) {
                                     $this->removeAttribute($vn_attribute_id);
                                 }
                             }
                         }
                         $this->update();
                     }
                     break;
                     # -------------------------------
                     // This bundle is only available for objects
                 # -------------------------------
                 // This bundle is only available for objects
                 case 'ca_objects_location':
                     if ($vb_batch) {
                         return null;
                     }
                     // not supported in batch mode
                     if (!$po_request->user->canDoAction('can_edit_ca_objects')) {
                         break;
                     }
                     if ($vn_location_id = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_location_idnew_0", pInteger)) {
                         if (is_array($va_relationship_types = caGetOption('ca_storage_locations_relationshipType', $va_bundle_settings, null)) && ($vn_relationship_type_id = array_shift($va_relationship_types))) {
                             $this->addRelationship('ca_storage_locations', $vn_location_id, $vn_relationship_type_id, null, null, null, null, array('allowDuplicates' => true));
                             if ($this->numErrors()) {
                                 $po_request->addActionErrors($this->errors(), 'ca_objects_location', 'general');
                             }
                         }
                     }
                     break;
                     # -------------------------------
                     // This bundle is only available for objects
                 # -------------------------------
                 // This bundle is only available for objects
                 case 'ca_objects_history':
                     if ($vb_batch) {
                         return null;
                     }
                     // not supported in batch mode
                     if (!$po_request->user->canDoAction('can_edit_ca_objects')) {
                         break;
                     }
                     // set storage location
                     if ($vn_location_id = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_location_idnew_0", pInteger)) {
                         if (is_array($va_relationship_types = caGetOption('ca_storage_locations_showRelationshipTypes', $va_bundle_settings, null)) && ($vn_relationship_type_id = array_shift($va_relationship_types))) {
                             $this->addRelationship('ca_storage_locations', $vn_location_id, $vn_relationship_type_id, null, null, null, null, array('allowDuplicates' => true));
                             if ($this->numErrors()) {
                                 $po_request->addActionErrors($this->errors(), 'ca_objects_history', 'general');
                             }
                         }
                     }
                     // set loan
                     if ($vn_loan_id = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_loan_idnew_0", pInteger)) {
                         if ($vn_loan_type_id = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}_loan_type_idnew_0", pInteger)) {
                             $this->addRelationship('ca_loans', $vn_loan_id, $vn_loan_type_id);
                             if ($this->numErrors()) {
                                 $po_request->addActionErrors($this->errors(), 'ca_objects_history', 'general');
                             }
                         }
                     }
                     break;
                     # -------------------------------
                     // This bundle is only available for objects
                 # -------------------------------
                 // This bundle is only available for objects
                 case 'ca_objects_deaccession':
                     // object deaccession information
                     if (!$vb_batch && !$this->getPrimaryKey()) {
                         return null;
                     }
                     // not supported for new records
                     if (!$po_request->user->canDoAction('can_edit_ca_objects')) {
                         break;
                     }
                     $this->set('is_deaccessioned', $vb_is_deaccessioned = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}is_deaccessioned", pInteger));
                     $this->set('deaccession_notes', $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}deaccession_notes", pString));
                     $this->set('deaccession_type_id', $x = $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}deaccession_type_id", pString));
                     $this->set('deaccession_date', $po_request->getParameter("{$vs_placement_code}{$vs_form_prefix}deaccession_date", pString));
                     if ($vb_is_deaccessioned && (bool) $this->getAppConfig()->get('deaccession_force_access_private')) {
                         $this->get('access', 0);
                     }
                     // set access to private for accessioned items
                     $this->update();
                     break;
                     # -------------------------------
                     // This bundle is only available for objects
                 # -------------------------------
                 // This bundle is only available for objects
                 case 'ca_object_checkouts':
                     // object checkout information
                     if ($vb_batch) {
                         return null;
                     }
                     // not supported in batch mode
                     if (!$vb_batch && !$this->getPrimaryKey()) {
                         return null;
                     }
                     // not supported for new records
                     if (!$po_request->user->canDoAction('can_edit_ca_objects')) {
                         break;
                     }
                     // NOOP (for now)
                     break;
                     # -------------------------------
             }
         }
     }
     BaseModel::unsetChangeLogUnitID();
     $va_bundle_names = array();
     foreach ($va_bundles as $va_bundle) {
         $vs_bundle_name = str_replace('ca_attribute_', '', $va_bundle['bundle_name']);
         if (!$this->getAppDatamodel()->getInstanceByTableName($vs_bundle_name, true)) {
             $vs_bundle_name = $this->tableName() . '.' . $vs_bundle_name;
         }
         $va_bundle_names[] = $vs_bundle_name;
     }
     // validate metadata dictionary rules
     $va_violations = $this->validateUsingMetadataDictionaryRules(array('bundles' => $va_bundle_names));
     if (sizeof($va_violations)) {
         if ($vb_we_set_transaction && isset($va_violations['ERR']) && is_array($va_violations['ERR']) && sizeof($va_violations['ERR']) > 0) {
             BaseModel::unsetChangeLogUnitID();
             $this->removeTransaction(false);
             $this->_FIELD_VALUES[$this->primaryKey()] = null;
             // clear primary key since transaction has been rolled back
             foreach ($va_violations['ERR'] as $vs_bundle => $va_errs_by_bundle) {
                 foreach ($va_errs_by_bundle as $vn_i => $va_rule) {
                     $vs_bundle = str_replace($this->tableName() . ".", "", $vs_bundle);
                     $po_request->addActionErrors(array(new Error(1100, $va_rule['rule_settings']['violationMessage'], "BundlableLabelableBaseModelWithAttributes->saveBundlesForScreen()", 'MetadataDictionary', false, false)), $vs_bundle, 'general');
                 }
             }
             return false;
         }
     }
     // prepopulate fields
     $vs_prepopulate_cfg = $this->getAppConfig()->get('prepopulate_config');
     $o_prepopulate_conf = Configuration::load($vs_prepopulate_cfg);
     if ($o_prepopulate_conf->get('prepopulate_fields_on_save')) {
         $this->prepopulateFields(array('prepopulateConfig' => $vs_prepopulate_cfg));
     }
     if ($vb_dryrun) {
         $this->removeTransaction(false);
     }
     if ($vb_we_set_transaction) {
         $this->removeTransaction(true);
     }
     return true;
 }
Пример #5
0
 /**
  * Processes single exporter item for a given record
  *
  * @param int $pn_item_id Primary of exporter item
  * @param int $pn_table_num Table num of item to export
  * @param int $pn_record_id Primary key value of item to export
  * @param array $pa_options
  *		ignoreContext = don't switch context even though context may be set for current item
  *		relationship_type_id, relationship_type_code, relationship_typename =
  *			if this export is a sub-export (context-switch), we have no way of knowing the relationship
  *			to the 'parent' element in the export, so there has to be a means to pass it down to make it accessible
  * 		attribute_id = signals that this is an export relative to a specific attribute instance
  * 			this triggers special behavior that allows getting container values in a kind of sub-export
  *			it's really only useful for Containers but in theory can be any attribute
  *		logger = KLogger instance to use for logging. This option is mandatory!
  * @return array Item info
  */
 public function processExporterItem($pn_item_id, $pn_table_num, $pn_record_id, $pa_options = array())
 {
     $o_log = caGetOption('logger', $pa_options);
     // always set by exportRecord()
     $vb_ignore_context = caGetOption('ignoreContext', $pa_options);
     $vn_attribute_id = caGetOption('attribute_id', $pa_options);
     $o_log->logInfo(_t("Export mapping processor called with parameters [exporter_item_id:%1 table_num:%2 record_id:%3]", $pn_item_id, $pn_table_num, $pn_record_id));
     $t_exporter_item = ca_data_exporters::loadExporterItemByID($pn_item_id);
     $t_instance = ca_data_exporters::loadInstanceByID($pn_record_id, $pn_table_num);
     // switch context to a different set of records if necessary and repeat current exporter item for all those selected records
     // (e.g. hierarchy children or related items in another table, restricted by types or relationship types)
     if (!$vb_ignore_context && ($vs_context = $t_exporter_item->getSetting('context'))) {
         $va_restrict_to_types = $t_exporter_item->getSetting('restrictToTypes');
         $va_restrict_to_rel_types = $t_exporter_item->getSetting('restrictToRelationshipTypes');
         $va_restrict_to_bundle_vals = $t_exporter_item->getSetting('restrictToBundleValues');
         $va_check_access = $t_exporter_item->getSetting('checkAccess');
         $va_sort = $t_exporter_item->getSetting('sort');
         $vn_new_table_num = $this->getAppDatamodel()->getTableNum($vs_context);
         $vb_context_is_related_table = false;
         $va_related = null;
         if ($vn_new_table_num) {
             // switch to new table
             $vs_key = $this->getAppDatamodel()->getTablePrimaryKeyName($vs_context);
         } else {
             // this table, i.e. hierarchy context switch
             $vs_key = $t_instance->primaryKey();
         }
         $o_log->logInfo(_t("Initiating context switch to '%1' for mapping ID %2 and record ID %3. The processor now tries to find matching records for the switch and calls itself for each of those items.", $vs_context, $pn_item_id, $pn_record_id));
         switch ($vs_context) {
             case 'children':
                 $va_related = $t_instance->getHierarchyChildren();
                 break;
             case 'parent':
                 $va_related = array();
                 if ($vs_parent_id_fld = $t_instance->getProperty("HIERARCHY_PARENT_ID_FLD")) {
                     $va_related[] = array($vs_key => $t_instance->get($vs_parent_id_fld));
                 }
                 break;
             case 'ancestors':
                 $va_parents = $t_instance->getHierarchyAncestors(null, array('idsOnly' => true));
                 $va_related = array();
                 foreach (array_unique($va_parents) as $vn_pk) {
                     $va_related[] = array($vs_key => intval($vn_pk));
                 }
                 break;
             case 'ca_sets':
                 $t_set = new ca_sets();
                 $va_set_options = array();
                 if (isset($va_restrict_to_types[0])) {
                     // the utility used below doesn't support passing multiple types so we just pass the first.
                     // this should be enough for 99.99% of the actual use cases anyway
                     $va_set_options['setType'] = $va_restrict_to_types[0];
                 }
                 $va_set_options['checkAccess'] = $va_check_access;
                 $va_set_options['setIDsOnly'] = true;
                 $va_set_ids = $t_set->getSetsForItem($pn_table_num, $t_instance->getPrimaryKey(), $va_set_options);
                 $va_related = array();
                 foreach (array_unique($va_set_ids) as $vn_pk) {
                     $va_related[] = array($vs_key => intval($vn_pk));
                 }
                 break;
             case 'ca_list_items.firstLevel':
                 if ($t_instance->tableName() == 'ca_lists') {
                     $o_dm = Datamodel::load();
                     $va_related = array();
                     $va_items_legacy_format = $t_instance->getListItemsAsHierarchy(null, array('maxLevels' => 1, 'dontIncludeRoot' => true));
                     $vn_new_table_num = $o_dm->getTableNum('ca_list_items');
                     $vs_key = 'item_id';
                     foreach ($va_items_legacy_format as $va_item_legacy_format) {
                         $va_related[$va_item_legacy_format['NODE']['item_id']] = $va_item_legacy_format['NODE'];
                     }
                     break;
                 } else {
                     return array();
                 }
                 break;
             default:
                 if ($vn_new_table_num) {
                     $va_options = array('restrictToTypes' => $va_restrict_to_types, 'restrictToRelationshipTypes' => $va_restrict_to_rel_types, 'restrictToBundleValues' => $va_restrict_to_bundle_vals, 'checkAccess' => $va_check_access, 'sort' => $va_sort);
                     $o_log->logDebug(_t("Calling getRelatedItems with options: %1.", print_r($va_options, true)));
                     $va_related = $t_instance->getRelatedItems($vs_context, $va_options);
                     $vb_context_is_related_table = true;
                 } else {
                     // container or invalid context
                     $va_context_tmp = explode('.', $vs_context);
                     if (sizeof($va_context_tmp) != 2) {
                         $o_log->logError(_t("Invalid context %1. Ignoring this mapping.", $vs_context));
                         return array();
                     }
                     $va_attrs = $t_instance->getAttributesByElement($va_context_tmp[1]);
                     $va_info = array();
                     if (is_array($va_attrs) && sizeof($va_attrs) > 0) {
                         $o_log->logInfo(_t("Switching context for element code: %1.", $va_context_tmp[1]));
                         $o_log->logDebug(_t("Raw attribute value array is as follows. The mapping will now be repeated for each (outer) attribute. %1", print_r($va_attrs, true)));
                         foreach ($va_attrs as $vo_attr) {
                             $va_attribute_export = $this->processExporterItem($pn_item_id, $pn_table_num, $pn_record_id, array_merge(array('ignoreContext' => true, 'attribute_id' => $vo_attr->getAttributeID()), $pa_options));
                             $va_info = array_merge($va_info, $va_attribute_export);
                         }
                     } else {
                         $o_log->logInfo(_t("Switching context for element code %1 failed. Either there is no attribute with that code attached to the current row or the code is invalid. Mapping is ignored for current row.", $va_context_tmp[1]));
                     }
                     return $va_info;
                 }
                 break;
         }
         $va_info = array();
         if (is_array($va_related)) {
             $o_log->logDebug(_t("The current mapping will now be repreated for these items: %1", print_r($va_related, true)));
             if (!$vn_new_table_num) {
                 $vn_new_table_num = $pn_table_num;
             }
             foreach ($va_related as $va_rel) {
                 // if we're dealing with a related table, pass on some info the relationship type to the context-switched invocation of processExporterItem(),
                 // because we can't access that information from the related item simply because we don't exactly know where the call originated
                 if ($vb_context_is_related_table) {
                     $pa_options['relationship_typename'] = $va_rel['relationship_typename'];
                     $pa_options['relationship_type_code'] = $va_rel['relationship_type_code'];
                     $pa_options['relationship_type_id'] = $va_rel['relationship_type_id'];
                 }
                 $va_rel_export = $this->processExporterItem($pn_item_id, $vn_new_table_num, $va_rel[$vs_key], array_merge(array('ignoreContext' => true), $pa_options));
                 $va_info = array_merge($va_info, $va_rel_export);
             }
         } else {
             $o_log->logDebug(_t("No matching related items found for last context switch"));
         }
         return $va_info;
     }
     // end switch context
     // Don't prevent context switches for children of context-switched exporter items. This way you can
     // build cascades for jobs like exporting objects related to the creator of the record in question.
     unset($pa_options['ignoreContext']);
     $va_item_info = array();
     $vs_source = $t_exporter_item->get('source');
     $vs_element = $t_exporter_item->get('element');
     $vb_repeat = $t_exporter_item->getSetting('repeat_element_for_multiple_values');
     // if omitIfEmpty is set and get() returns nothing, we ignore this exporter item and all children
     if ($vs_omit_if_empty = $t_exporter_item->getSetting('omitIfEmpty')) {
         if (!(strlen($t_instance->get($vs_omit_if_empty)) > 0)) {
             return array();
         }
     }
     // if omitIfNotEmpty is set and get() returns a value, we ignore this exporter item and all children
     if ($vs_omit_if_not_empty = $t_exporter_item->getSetting('omitIfNotEmpty')) {
         if (strlen($t_instance->get($vs_omit_if_not_empty)) > 0) {
             return array();
         }
     }
     // always return URL for export, not an HTML tag
     $va_get_options = array('returnURL' => true);
     if ($vs_delimiter = $t_exporter_item->getSetting("delimiter")) {
         $va_get_options['delimiter'] = $vs_delimiter;
     }
     if ($vs_template = $t_exporter_item->getSetting('template')) {
         $va_get_options['template'] = $vs_template;
     }
     if ($vs_locale = $t_exporter_item->getSetting('locale')) {
         // the global UI locale for some reason has a higher priority
         // than the locale setting in BaseModelWithAttributes::get
         // which is why we unset it here and restore it later
         global $g_ui_locale;
         $vs_old_ui_locale = $g_ui_locale;
         $g_ui_locale = null;
         $va_get_options['locale'] = $vs_locale;
     }
     // AttributeValue settings that are simply passed through by the exporter
     if ($t_exporter_item->getSetting('convertCodesToDisplayText')) {
         $va_get_options['convertCodesToDisplayText'] = true;
         // try to return text suitable for display for system lists stored in intrinsics (ex. ca_objects.access, ca_objects.status, ca_objects.source_id)
         // this does not affect list attributes
     } else {
         $va_get_options['convertCodesToIdno'] = true;
         // if display text is not requested try to return list item idno's... since underlying integer ca_list_items.item_id values are unlikely to be useful in an export context
     }
     if ($t_exporter_item->getSetting('returnIdno')) {
         $va_get_options['returnIdno'] = true;
     }
     if ($t_exporter_item->getSetting('start_as_iso8601')) {
         $va_get_options['start_as_iso8601'] = true;
     }
     if ($t_exporter_item->getSetting('end_as_iso8601')) {
         $va_get_options['end_as_iso8601'] = true;
     }
     if ($t_exporter_item->getSetting('dontReturnValueIfOnSameDayAsStart')) {
         $va_get_options['dontReturnValueIfOnSameDayAsStart'] = true;
     }
     if ($vs_date_format = $t_exporter_item->getSetting('dateFormat')) {
         $va_get_options['dateFormat'] = $vs_date_format;
     }
     // context was switched to attribute
     if ($vn_attribute_id) {
         $o_log->logInfo(_t("Processing mapping in attribute mode for attribute_id = %1.", $vn_attribute_id));
         if ($vs_source) {
             // trying to find the source only makes sense if the source is set
             $t_attr = new ca_attributes($vn_attribute_id);
             $va_values = $t_attr->getAttributeValues();
             $va_src_tmp = explode('.', $vs_source);
             if (sizeof($va_src_tmp) == 2) {
                 $o_dm = Datamodel::load();
                 if ($t_attr->get('table_num') == $o_dm->getTableNum($va_src_tmp[0])) {
                     $vs_source = $va_src_tmp[1];
                 }
             }
             $o_log->logDebug(_t("Trying to find code %1 in value array for the current attribute.", $vs_source));
             $o_log->logDebug(_t("Value array is %1.", print_r($va_values, true)));
             foreach ($va_values as $vo_val) {
                 $va_display_val_options = array();
                 if ($vo_val instanceof ListAttributeValue) {
                     // figure out list_id -- without it we can't pull display values
                     $t_element = new ca_metadata_elements($vo_val->getElementID());
                     $va_display_val_options = array('list_id' => $t_element->get('list_id'));
                     if ($t_exporter_item->getSetting('returnIdno') || $t_exporter_item->getSetting('convertCodesToIdno')) {
                         $va_display_val_options['output'] = 'idno';
                     } elseif ($t_exporter_item->getSetting('convertCodesToDisplayText')) {
                         $va_display_val_options['output'] = 'text';
                     }
                 }
                 $o_log->logDebug(_t("Trying to match code from array %1 and the code we're looking for %2.", $vo_val->getElementCode(), $vs_source));
                 if ($vo_val->getElementCode() == $vs_source) {
                     $vs_display_value = $vo_val->getDisplayValue($va_display_val_options);
                     $o_log->logDebug(_t("Found value %1.", $vs_display_value));
                     $va_item_info[] = array('text' => $vs_display_value, 'element' => $vs_element);
                 }
             }
         } else {
             // no source in attribute context probably means this is some form of wrapper, e.g. a MARC field
             $va_item_info[] = array('element' => $vs_element);
         }
     } else {
         if ($vs_source) {
             $o_log->logDebug(_t("Source for current mapping is %1", $vs_source));
             $va_matches = array();
             // CONSTANT value
             if (preg_match("/^_CONSTANT_:(.*)\$/", $vs_source, $va_matches)) {
                 $o_log->logDebug(_t("This is a constant. Value for this mapping is '%1'", trim($va_matches[1])));
                 $va_item_info[] = array('text' => trim($va_matches[1]), 'element' => $vs_element);
             } else {
                 if (in_array($vs_source, array("relationship_type_id", "relationship_type_code", "relationship_typename"))) {
                     if (isset($pa_options[$vs_source]) && strlen($pa_options[$vs_source]) > 0) {
                         $o_log->logDebug(_t("Source refers to releationship type information. Value for this mapping is '%1'", $pa_options[$vs_source]));
                         $va_item_info[] = array('text' => $pa_options[$vs_source], 'element' => $vs_element);
                     }
                 } else {
                     if (!$vb_repeat) {
                         $vs_get = $t_instance->get($vs_source, $va_get_options);
                         $o_log->logDebug(_t("Source is a simple get() for some bundle. Value for this mapping is '%1'", $vs_get));
                         $o_log->logDebug(_t("get() options are: %1", print_r($va_get_options, true)));
                         $va_item_info[] = array('text' => $vs_get, 'element' => $vs_element);
                     } else {
                         // user wants current element repeated in case of multiple returned values
                         $va_get_options['delimiter'] = ';#;';
                         $vs_values = $t_instance->get($vs_source, $va_get_options);
                         $o_log->logDebug(_t("Source is a get() that should be repeated for multiple values. Value for this mapping is '%1'. It includes the custom delimiter ';#;' that is later used to split the value into multiple values.", $vs_values));
                         $o_log->logDebug(_t("get() options are: %1", print_r($va_get_options, true)));
                         $va_tmp = explode(";#;", $vs_values);
                         foreach ($va_tmp as $vs_text) {
                             $va_item_info[] = array('element' => $vs_element, 'text' => $vs_text);
                         }
                     }
                 }
             }
         } else {
             if ($vs_template) {
                 // templates without source are probably just static text, but you never know
                 // -> run them through processor anyways
                 $vs_proc_template = caProcessTemplateForIDs($vs_template, $pn_table_num, array($pn_record_id), array());
                 $o_log->logDebug(_t("Current mapping has no source but a template '%1'. Value from extracted via template processor is '%2'", $vs_template, $vs_proc_template));
                 $va_item_info[] = array('element' => $vs_element, 'text' => $vs_proc_template);
             } else {
                 // no source, no template -> probably wrapper
                 $o_log->logDebug(_t("Current mapping has no source and no template and is probably an XML/MARC wrapper element"));
                 $va_item_info[] = array('element' => $vs_element);
             }
         }
     }
     // reset UI locale if we unset it
     if ($vs_locale) {
         $g_ui_locale = $vs_old_ui_locale;
     }
     $o_log->logDebug(_t("We're now processing other settings like default, prefix, suffix, skipIfExpression, filterByRegExp, maxLength, plugins and replacements for this mapping"));
     $o_log->logDebug(_t("Local data before processing is: %1", print_r($va_item_info, true)));
     // handle other settings and plugin hooks
     $vs_default = $t_exporter_item->getSetting('default');
     $vs_prefix = $t_exporter_item->getSetting('prefix');
     $vs_suffix = $t_exporter_item->getSetting('suffix');
     //$vs_regexp = $t_exporter_item->getSetting('filterByRegExp');		// Deprecated -- remove?
     $vn_max_length = $t_exporter_item->getSetting('maxLength');
     $vs_skip_if_expr = $t_exporter_item->getSetting('skipIfExpression');
     $vs_original_values = $t_exporter_item->getSetting('original_values');
     $vs_replacement_values = $t_exporter_item->getSetting('replacement_values');
     $va_replacements = ca_data_exporter_items::getReplacementArray($vs_original_values, $vs_replacement_values);
     foreach ($va_item_info as $vn_key => &$va_item) {
         $this->opo_app_plugin_manager->hookExportItemBeforeSettings(array('instance' => $t_instance, 'exporter_item_instance' => $t_exporter_item, 'export_item' => &$va_item));
         // handle dontReturnValueIfOnSameDayAsStart
         if (caGetOption('dontReturnValueIfOnSameDayAsStart', $va_get_options, false)) {
             if (strlen($va_item['text']) < 1) {
                 unset($va_item_info[$vn_key]);
             }
         }
         // handle skipIfExpression setting
         if ($vs_skip_if_expr) {
             // Add current value as variable "value", accessible in expressions as ^value
             $va_vars = array_merge(array('value' => $va_item['text']), ca_data_exporters::$s_variables);
             if (ExpressionParser::evaluate($vs_skip_if_expr, $va_vars)) {
                 unset($va_item_info[$vn_key]);
                 continue;
             }
         }
         // filter by regex (deprecated since you can do the same thing and more with skipIfExpression) -- remove?
         //if((strlen($va_item['text'])>0) && $vs_regexp) {
         //	if(!preg_match("!".$vs_regexp."!i", $va_item['text'])) {
         //		unset($va_item_info[$vn_key]);
         //		continue;
         //	}
         //}
         // do replacements
         $va_item['text'] = ca_data_exporter_items::replaceText($va_item['text'], $va_replacements);
         // if text is empty, fill in default
         // if text isn't empty, respect prefix and suffix
         if (strlen($va_item['text']) == 0) {
             if ($vs_default) {
                 $va_item['text'] = $vs_default;
             }
         } else {
             if (strlen($vs_prefix) > 0 || strlen($vs_suffix) > 0) {
                 $va_item['text'] = $vs_prefix . $va_item['text'] . $vs_suffix;
             }
         }
         if ($vn_max_length && strlen($va_item['text']) > $vn_max_length) {
             $va_item['text'] = substr($va_item['text'], 0, $vn_max_length) . " ...";
         }
         // if this is a variable, set the value and delete it from the export tree
         $va_matches = array();
         if (preg_match("/^_VARIABLE_:(.*)\$/", $va_item['element'], $va_matches)) {
             ca_data_exporters::$s_variables[$va_matches[1]] = $va_item['text'];
             unset($va_item_info[$vn_key]);
             continue;
         }
         // if returned value is null then we skip the item
         $this->opo_app_plugin_manager->hookExportItem(array('instance' => $t_instance, 'exporter_item_instance' => $t_exporter_item, 'export_item' => &$va_item));
     }
     $o_log->logInfo(_t("Extracted data for this mapping is as follows:"));
     foreach ($va_item_info as $va_tmp) {
         $o_log->logInfo(sprintf("    element:%-20s value: %-10s", $va_tmp['element'], $va_tmp['text']));
     }
     $va_children = $t_exporter_item->getHierarchyChildren();
     if (is_array($va_children) && sizeof($va_children) > 0) {
         $o_log->logInfo(_t("Now proceeding to process %1 direct children in the mapping hierarchy", sizeof($va_children)));
         foreach ($va_children as $va_child) {
             foreach ($va_item_info as &$va_info) {
                 $va_child_export = $this->processExporterItem($va_child['item_id'], $pn_table_num, $pn_record_id, $pa_options);
                 $va_info['children'] = array_merge((array) $va_info['children'], $va_child_export);
             }
         }
     }
     return $va_item_info;
 }
        }
    }
    if ($vs_style_display) {
        print "<H6>" . _t("Style/Movement") . "</H6>";
        print $vs_style_display;
    }
}
$va_collections = $t_object->get("ca_collections", array("returnAsArray" => true, "checkAccess" => $va_access_values, "sort" => "ca_collections.preferred_labels.name"));
if (sizeof($va_collections)) {
    print "<H6>Collection" . (sizeof($va_collections) > 1 ? "s" : "") . "</H6>";
    foreach ($va_collections as $va_collection) {
        print caDetailLink($this->request, $va_collection["name"], "", "ca_collections", $va_collection["collection_id"]) . "<br/>";
    }
}
$t_set = new ca_sets();
$va_galleries = caExtractValuesByUserLocale($t_set->getSetsForItem("ca_objects", $t_object->get("object_id"), array("checkAccess" => $va_access_values, "setType" => "public_presentation")));
if (sizeof($va_galleries)) {
    print "<H6>Galler" . (sizeof($va_galleries) > 1 ? "ies" : "y") . "</H6>";
    foreach ($va_galleries as $va_gallery) {
        print caNavLink($this->request, $va_gallery["name"], "", "", "Gallery", $va_gallery["set_id"]) . "<br/>";
    }
}
if ($va_themes = $t_object->get("ca_objects.steelcase_themes", array("returnAsArray" => true, "convertCodesToDisplayText" => false))) {
    $i = 0;
    $vs_theme_display = "";
    foreach ($va_themes as $vn_theme_id => $va_theme) {
        $i++;
        $vs_theme = $t_lists->getItemFromListForDisplayByItemID("custom_subject", $va_theme["steelcase_themes"]);
        if (trim($vs_theme)) {
            $vs_theme_display .= caNavLink($this->request, $vs_theme, "", "", "Browse", "Objects", array("facet" => "theme_facet", "id" => $va_theme["steelcase_themes"]));
            if ($i < sizeof($va_themes)) {
Пример #7
0
 /**
  * @param array $pa_options
  *		ignoreContext = don't switch context even though context may be set for current item
  */
 public function processExporterItem($pn_item_id, $pn_table_num, $pn_record_id, $pa_options = array())
 {
     $vb_ignore_context = isset($pa_options['ignoreContext']) && $pa_options['ignoreContext'];
     $t_exporter_item = ca_data_exporters::loadExporterItemByID($pn_item_id);
     $t_instance = ca_data_exporters::loadInstanceByID($pn_record_id, $pn_table_num);
     // switch context to a different set of records if necessary and repeat current exporter item for all those selected records
     // (e.g. hierarchy children or related items in another table, restricted by types or relationship types)
     if (!$vb_ignore_context && ($vs_context = $t_exporter_item->getSetting('context'))) {
         $va_restrict_to_types = $t_exporter_item->getSetting('restrictToTypes');
         $va_restrict_to_rel_types = $t_exporter_item->getSetting('restrictToRelationshipTypes');
         $va_check_access = $t_exporter_item->getSetting('checkAccess');
         $vn_new_table_num = $this->getAppDatamodel()->getTableNum($vs_context);
         if ($vn_new_table_num) {
             // switch to new table
             $vs_key = $this->getAppDatamodel()->getTablePrimaryKeyName($vs_context);
         } else {
             // this table, i.e. hierarchy context switch
             $vs_key = $t_instance->primaryKey();
             $vn_new_table_num = $pn_table_num;
         }
         switch ($vs_context) {
             case 'children':
                 $va_related = $t_instance->getHierarchyChildren();
                 break;
             case 'parent':
                 $va_related = array();
                 if ($vs_parent_id_fld = $t_instance->getProperty("HIERARCHY_PARENT_ID_FLD")) {
                     $va_related[] = array($vs_key => $t_instance->get($vs_parent_id_fld));
                 }
                 break;
             case 'ancestors':
                 $va_parents = $t_instance->getHierarchyAncestors(null, array('idsOnly' => true));
                 $va_related = array();
                 foreach (array_unique($va_parents) as $vn_pk) {
                     $va_related[] = array($vs_key => intval($vn_pk));
                 }
                 break;
             case 'ca_sets':
                 $t_set = new ca_sets();
                 $va_set_options = array();
                 if (isset($va_restrict_to_types[0])) {
                     // the utility used below doesn't support passing multiple types so we just pass the first.
                     // this should be enough for 99.99% of the actual use cases anyway
                     $va_set_options['setType'] = $va_restrict_to_types[0];
                 }
                 $va_set_options['checkAccess'] = $va_check_access;
                 $va_set_options['setIDsOnly'] = true;
                 $va_set_ids = $t_set->getSetsForItem($pn_table_num, $t_instance->getPrimaryKey(), $va_set_options);
                 $va_related = array();
                 foreach (array_unique($va_set_ids) as $vn_pk) {
                     $va_related[] = array($vs_key => intval($vn_pk));
                 }
                 break;
             default:
                 // plain old related table
                 if ($vn_new_table_num) {
                     $va_related = $t_instance->getRelatedItems($vs_context, array('restrictToTypes' => $va_restrict_to_types, 'restrictToRelationshipTypes' => $va_restrict_to_rel_types, 'checkAccess' => $va_check_access));
                 } else {
                     return array();
                 }
                 break;
         }
         $va_info = array();
         if (is_array($va_related)) {
             foreach ($va_related as $va_rel) {
                 $va_rel_export = $this->processExporterItem($pn_item_id, $vn_new_table_num, $va_rel[$vs_key], array_merge(array('ignoreContext' => true), $pa_options));
                 $va_info = array_merge($va_info, $va_rel_export);
             }
         }
         return $va_info;
     }
     // end switch context
     // Don't prevent context switches for children of context-switched exporter items. This way you can
     // build cascades for jobs like exporting objects related to the creator of the record in question.
     unset($pa_options['ignoreContext']);
     $va_item_info = array();
     $vs_source = $t_exporter_item->get('source');
     $vs_element = $t_exporter_item->get('element');
     $vb_repeat = $t_exporter_item->getSetting('repeat_element_for_multiple_values');
     // if omitIfEmpty is set and returns nothing, we ignore this exporter item and all children
     if ($vs_omit_if_empty = $t_exporter_item->getSetting('omitIfEmpty')) {
         if (!(strlen($t_instance->get($vs_omit_if_empty)) > 0)) {
             return array();
         }
     }
     // always return URL for export, not an HTML tag
     $va_get_options = array('returnURL' => true);
     if ($t_exporter_item->getSetting('convertCodesToDisplayText')) {
         $va_get_options['convertCodesToDisplayText'] = true;
     }
     if ($vs_delimiter = $t_exporter_item->getSetting("delimiter")) {
         $va_get_options['delimiter'] = $vs_delimiter;
     }
     if ($vs_template = $t_exporter_item->getSetting('template')) {
         $va_get_options['template'] = $vs_template;
     }
     if ($vs_locale = $t_exporter_item->getSetting('locale')) {
         // the global UI locale for some reason has a higher priority
         // than the locale setting in BaseModelWithAttributes::get
         // which is why we unset it here and restore it later
         global $g_ui_locale;
         $vs_old_ui_locale = $g_ui_locale;
         $g_ui_locale = null;
         $va_get_options['locale'] = $vs_locale;
     }
     if ($vs_source) {
         $va_matches = array();
         // CONSTANT value
         if (preg_match("/^_CONSTANT_:(.*)\$/", $vs_source, $va_matches)) {
             $va_item_info[] = array('text' => trim($va_matches[1]), 'element' => $vs_element);
         } else {
             if (!$vb_repeat) {
                 $va_item_info[] = array('text' => $t_instance->get($vs_source, $va_get_options), 'element' => $vs_element);
             } else {
                 // if user wants current element repeated in case of multiple returned values, go ahead and do that
                 $va_get_options['delimiter'] = ';#;';
                 $vs_values = $t_instance->get($vs_source, $va_get_options);
                 $va_tmp = explode(";#;", $vs_values);
                 foreach ($va_tmp as $vs_text) {
                     $va_item_info[] = array('element' => $vs_element, 'text' => $vs_text);
                 }
             }
         }
     } else {
         if ($vs_template) {
             // templates without source are probably just static text, but you never know
             // -> run them through processor anyways
             $va_item_info[] = array('element' => $vs_element, 'text' => caProcessTemplateForIDs($vs_template, $pn_table_num, array($pn_record_id), array()));
         } else {
             // no source, no template -> probably wrapper
             $va_item_info[] = array('element' => $vs_element);
         }
     }
     // reset UI locale if we unset it
     if ($vs_locale) {
         $g_ui_locale = $vs_old_ui_locale;
     }
     // handle settings and plugin hooks
     $vs_default = $t_exporter_item->getSetting('default');
     $vs_prefix = $t_exporter_item->getSetting('prefix');
     $vs_suffix = $t_exporter_item->getSetting('suffix');
     $vs_regexp = $t_exporter_item->getSetting('filterByRegExp');
     $vn_maxlength = $t_exporter_item->getSetting('maxLength');
     $vs_original_values = $t_exporter_item->getSetting('original_values');
     $vs_replacement_values = $t_exporter_item->getSetting('replacement_values');
     $va_replacements = ca_data_exporter_items::getReplacementArray($vs_original_values, $vs_replacement_values);
     foreach ($va_item_info as $vn_key => &$va_item) {
         // if returned value is null then we skip the item
         if (is_null($va_plugin_item = $this->opo_app_plugin_manager->hookExportItemBeforeSettings(array('instance' => $t_instance, 'exporter_item_instance' => $t_exporter_item, 'export_item' => $va_item)))) {
             continue;
         } else {
             $va_item = $va_plugin_item['export_item'];
         }
         // filter by regexp
         if (strlen($va_item['text']) > 0 && $vs_regexp) {
             if (!preg_match("!" . $vs_regexp . "!", $va_item['text'])) {
                 unset($va_item_info[$vn_key]);
                 continue;
             }
         }
         // do replacements
         $va_item['text'] = ca_data_exporter_items::replaceText($va_item['text'], $va_replacements);
         // if text is empty, fill in default
         // if text isn't empty, respect prefix and suffix
         if (strlen($va_item['text']) == 0) {
             if ($vs_default) {
                 $va_item['text'] = $vs_default;
             }
         } else {
             if (strlen($vs_prefix) > 0 || strlen($vs_suffix) > 0) {
                 $va_item['text'] = $vs_prefix . $va_item['text'] . $vs_suffix;
             }
         }
         if ($vn_maxlength && strlen($va_item['text']) > $vn_maxlength) {
             $va_item['text'] = substr($va_item['text'], 0, $vn_maxlength) . " ...";
         }
         // if returned value is null then we skip the item
         if (is_null($va_plugin_item = $this->opo_app_plugin_manager->hookExportItem(array('instance' => $t_instance, 'exporter_item_instance' => $t_exporter_item, 'export_item' => $va_item)))) {
             continue;
         } else {
             $va_item = $va_plugin_item['export_item'];
         }
     }
     foreach ($t_exporter_item->getHierarchyChildren() as $va_child) {
         foreach ($va_item_info as &$va_item) {
             $va_child_export = $this->processExporterItem($va_child['item_id'], $pn_table_num, $pn_record_id, $pa_options);
             $va_item['children'] = array_merge((array) $va_item['children'], $va_child_export);
         }
     }
     return $va_item_info;
 }
Пример #8
0
 /**
  * Processes single exporter item for a given record
  *
  * @param int $pn_item_id Primary of exporter item
  * @param int $pn_table_num Table num of item to export
  * @param int $pn_record_id Primary key value of item to export
  * @param array $pa_options
  *		ignoreContext = don't switch context even though context may be set for current item
  *		relationship_type_id, relationship_type_code, relationship_typename =
  *			if this export is a sub-export (context-switch), we have no way of knowing the relationship
  *			to the 'parent' element in the export, so there has to be a means to pass it down to make it accessable
  *		logger = KLogger instance to use for logging. This option is mandatory!
  * @return array Item info
  */
 public function processExporterItem($pn_item_id, $pn_table_num, $pn_record_id, $pa_options = array())
 {
     $o_log = caGetOption('logger', $pa_options);
     // always set by exportRecord()
     $vb_ignore_context = caGetOption('ignoreContext', $pa_options);
     $o_log->logInfo(_t("Export mapping processor called with parameters [exporter_item_id:%1 table_num:%2 record_id:%3]", $pn_item_id, $pn_table_num, $pn_record_id));
     $t_exporter_item = ca_data_exporters::loadExporterItemByID($pn_item_id);
     $t_instance = ca_data_exporters::loadInstanceByID($pn_record_id, $pn_table_num);
     // switch context to a different set of records if necessary and repeat current exporter item for all those selected records
     // (e.g. hierarchy children or related items in another table, restricted by types or relationship types)
     if (!$vb_ignore_context && ($vs_context = $t_exporter_item->getSetting('context'))) {
         $va_restrict_to_types = $t_exporter_item->getSetting('restrictToTypes');
         $va_restrict_to_rel_types = $t_exporter_item->getSetting('restrictToRelationshipTypes');
         $va_check_access = $t_exporter_item->getSetting('checkAccess');
         $vn_new_table_num = $this->getAppDatamodel()->getTableNum($vs_context);
         $vb_context_is_related_table = false;
         if ($vn_new_table_num) {
             // switch to new table
             $vs_key = $this->getAppDatamodel()->getTablePrimaryKeyName($vs_context);
         } else {
             // this table, i.e. hierarchy context switch
             $vs_key = $t_instance->primaryKey();
             $vn_new_table_num = $pn_table_num;
         }
         $o_log->logInfo(_t("Initiating context switch to '%1' for mapping ID %2 and record ID %3. The processor now tries to find matching records for the switch and calls himself for each of those items.", $vs_context, $pn_item_id, $pn_record_id));
         switch ($vs_context) {
             case 'children':
                 $va_related = $t_instance->getHierarchyChildren();
                 break;
             case 'parent':
                 $va_related = array();
                 if ($vs_parent_id_fld = $t_instance->getProperty("HIERARCHY_PARENT_ID_FLD")) {
                     $va_related[] = array($vs_key => $t_instance->get($vs_parent_id_fld));
                 }
                 break;
             case 'ancestors':
                 $va_parents = $t_instance->getHierarchyAncestors(null, array('idsOnly' => true));
                 $va_related = array();
                 foreach (array_unique($va_parents) as $vn_pk) {
                     $va_related[] = array($vs_key => intval($vn_pk));
                 }
                 break;
             case 'ca_sets':
                 $t_set = new ca_sets();
                 $va_set_options = array();
                 if (isset($va_restrict_to_types[0])) {
                     // the utility used below doesn't support passing multiple types so we just pass the first.
                     // this should be enough for 99.99% of the actual use cases anyway
                     $va_set_options['setType'] = $va_restrict_to_types[0];
                 }
                 $va_set_options['checkAccess'] = $va_check_access;
                 $va_set_options['setIDsOnly'] = true;
                 $va_set_ids = $t_set->getSetsForItem($pn_table_num, $t_instance->getPrimaryKey(), $va_set_options);
                 $va_related = array();
                 foreach (array_unique($va_set_ids) as $vn_pk) {
                     $va_related[] = array($vs_key => intval($vn_pk));
                 }
                 break;
             default:
                 // plain old related table
                 if ($vn_new_table_num) {
                     $va_related = $t_instance->getRelatedItems($vs_context, array('restrictToTypes' => $va_restrict_to_types, 'restrictToRelationshipTypes' => $va_restrict_to_rel_types, 'checkAccess' => $va_check_access));
                     $vb_context_is_related_table = true;
                 } else {
                     return array();
                 }
                 break;
         }
         $va_info = array();
         if (is_array($va_related)) {
             $o_log->logDebug(_t("The current mapping will now be repreated for these items: %1", print_r($va_related, true)));
             foreach ($va_related as $va_rel) {
                 // if we're dealing with a related table, pass on some info the relationship type to the context-switched invocation of processExporterItem(),
                 // because we can't access that information from the related item simply because we don't exactly know where the call originated
                 if ($vb_context_is_related_table) {
                     $pa_options['relationship_typename'] = $va_rel['relationship_typename'];
                     $pa_options['relationship_type_code'] = $va_rel['relationship_type_code'];
                     $pa_options['relationship_type_id'] = $va_rel['relationship_type_id'];
                 }
                 $va_rel_export = $this->processExporterItem($pn_item_id, $vn_new_table_num, $va_rel[$vs_key], array_merge(array('ignoreContext' => true), $pa_options));
                 $va_info = array_merge($va_info, $va_rel_export);
             }
         } else {
             $o_log->logDebug(_t("No matching related items found for last context switch"));
         }
         return $va_info;
     }
     // end switch context
     // Don't prevent context switches for children of context-switched exporter items. This way you can
     // build cascades for jobs like exporting objects related to the creator of the record in question.
     unset($pa_options['ignoreContext']);
     $va_item_info = array();
     $vs_source = $t_exporter_item->get('source');
     $vs_element = $t_exporter_item->get('element');
     $vb_repeat = $t_exporter_item->getSetting('repeat_element_for_multiple_values');
     // if omitIfEmpty is set and get() returns nothing, we ignore this exporter item and all children
     if ($vs_omit_if_empty = $t_exporter_item->getSetting('omitIfEmpty')) {
         if (!(strlen($t_instance->get($vs_omit_if_empty)) > 0)) {
             return array();
         }
     }
     // always return URL for export, not an HTML tag
     $va_get_options = array('returnURL' => true);
     if ($t_exporter_item->getSetting('convertCodesToDisplayText')) {
         $va_get_options['convertCodesToDisplayText'] = true;
     }
     if ($t_exporter_item->getSetting('returnIdno')) {
         $va_get_options['returnIdno'] = true;
     }
     if ($vs_delimiter = $t_exporter_item->getSetting("delimiter")) {
         $va_get_options['delimiter'] = $vs_delimiter;
     }
     if ($vs_template = $t_exporter_item->getSetting('template')) {
         $va_get_options['template'] = $vs_template;
     }
     if ($vs_locale = $t_exporter_item->getSetting('locale')) {
         // the global UI locale for some reason has a higher priority
         // than the locale setting in BaseModelWithAttributes::get
         // which is why we unset it here and restore it later
         global $g_ui_locale;
         $vs_old_ui_locale = $g_ui_locale;
         $g_ui_locale = null;
         $va_get_options['locale'] = $vs_locale;
     }
     if ($vs_source) {
         $o_log->logDebug(_t("Source for current mapping is %1", $vs_source));
         $va_matches = array();
         // CONSTANT value
         if (preg_match("/^_CONSTANT_:(.*)\$/", $vs_source, $va_matches)) {
             $o_log->logDebug(_t("This is a constant. Value for this mapping is '%1'", trim($va_matches[1])));
             $va_item_info[] = array('text' => trim($va_matches[1]), 'element' => $vs_element);
         } else {
             if (in_array($vs_source, array("relationship_type_id", "relationship_type_code", "relationship_typename"))) {
                 if (isset($pa_options[$vs_source]) && strlen($pa_options[$vs_source]) > 0) {
                     $o_log->logDebug(_t("Source refers to releationship type information. Value for this mapping is '%1'", $pa_options[$vs_source]));
                     $va_item_info[] = array('text' => $pa_options[$vs_source], 'element' => $vs_element);
                 }
             } else {
                 if (!$vb_repeat) {
                     $vs_get = $t_instance->get($vs_source, $va_get_options);
                     $o_log->logDebug(_t("Source is a simple get() for some bundle. Value for this mapping is '%1'", $vs_get));
                     $o_log->logDebug(_t("get() options are: %1", print_r($va_get_options, true)));
                     $va_item_info[] = array('text' => $vs_get, 'element' => $vs_element);
                 } else {
                     // if user wants current element repeated in case of multiple returned values, go ahead and do that
                     $va_get_options['delimiter'] = ';#;';
                     $vs_values = $t_instance->get($vs_source, $va_get_options);
                     $o_log->logDebug(_t("Source is a get() that should be repeated for multiple values. Value for this mapping is '%1'. It includes the custom delimiter ';#;' that is later used to split the value into multiple values.", $vs_values));
                     $o_log->logDebug(_t("get() options are: %1", print_r($va_get_options, true)));
                     $va_tmp = explode(";#;", $vs_values);
                     foreach ($va_tmp as $vs_text) {
                         $va_item_info[] = array('element' => $vs_element, 'text' => $vs_text);
                     }
                 }
             }
         }
     } else {
         if ($vs_template) {
             // templates without source are probably just static text, but you never know
             // -> run them through processor anyways
             $vs_proc_template = caProcessTemplateForIDs($vs_template, $pn_table_num, array($pn_record_id), array());
             $o_log->logDebug(_t("Current mapping has no source but a template '%1'. Value from extracted via template processor is '%2'", $vs_template, $vs_proc_template));
             $va_item_info[] = array('element' => $vs_element, 'text' => $vs_proc_template);
         } else {
             // no source, no template -> probably wrapper
             $o_log->logDebug(_t("Current mapping has no source and no template and is probably an XML/MARC wrapper element"));
             $va_item_info[] = array('element' => $vs_element);
         }
     }
     // reset UI locale if we unset it
     if ($vs_locale) {
         $g_ui_locale = $vs_old_ui_locale;
     }
     $o_log->logDebug(_t("We're now processing other settings like default, prefix, suffix, skipIfExpression, filterByRegExp, maxLength, plugins and replacements for this mapping"));
     $o_log->logDebug(_t("Local data before processing is: %1", print_r($va_item_info, true)));
     // handle other settings and plugin hooks
     $vs_default = $t_exporter_item->getSetting('default');
     $vs_prefix = $t_exporter_item->getSetting('prefix');
     $vs_suffix = $t_exporter_item->getSetting('suffix');
     $vs_regexp = $t_exporter_item->getSetting('filterByRegExp');
     $vn_max_length = $t_exporter_item->getSetting('maxLength');
     $vs_skip_if_expr = $t_exporter_item->getSetting('skipIfExpression');
     $vs_original_values = $t_exporter_item->getSetting('original_values');
     $vs_replacement_values = $t_exporter_item->getSetting('replacement_values');
     $va_replacements = ca_data_exporter_items::getReplacementArray($vs_original_values, $vs_replacement_values);
     foreach ($va_item_info as $vn_key => &$va_item) {
         // if returned value from plugin is null then we skip the item
         if (is_null($va_plugin_item = $this->opo_app_plugin_manager->hookExportItemBeforeSettings(array('instance' => $t_instance, 'exporter_item_instance' => $t_exporter_item, 'export_item' => $va_item)))) {
             continue;
         } else {
             $va_item = $va_plugin_item['export_item'];
         }
         // handle skipIfExpression setting
         if ($vs_skip_if_expr) {
             // Add current value as variable "value", accessible in expressions as ^value
             if (ExpressionParser::evaluate($vs_skip_if_expr, array_merge(array('value' => $va_item['text']), ca_data_exporters::$s_variables))) {
                 unset($va_item_info[$vn_key]);
                 continue;
             }
         }
         // filter by regex (deprecated since you can do the same thing and more with skipIfExpression)
         if (strlen($va_item['text']) > 0 && $vs_regexp) {
             if (!preg_match("!" . $vs_regexp . "!", $va_item['text'])) {
                 unset($va_item_info[$vn_key]);
                 continue;
             }
         }
         // do replacements
         $va_item['text'] = ca_data_exporter_items::replaceText($va_item['text'], $va_replacements);
         // if text is empty, fill in default
         // if text isn't empty, respect prefix and suffix
         if (strlen($va_item['text']) == 0) {
             if ($vs_default) {
                 $va_item['text'] = $vs_default;
             }
         } else {
             if (strlen($vs_prefix) > 0 || strlen($vs_suffix) > 0) {
                 $va_item['text'] = $vs_prefix . $va_item['text'] . $vs_suffix;
             }
         }
         if ($vn_max_length && strlen($va_item['text']) > $vn_max_length) {
             $va_item['text'] = substr($va_item['text'], 0, $vn_max_length) . " ...";
         }
         // if this is a variable, set the value and delete it from the export tree
         $va_matches = array();
         if (preg_match("/^_VARIABLE_:(.*)\$/", $va_item['element'], $va_matches)) {
             ca_data_exporters::$s_variables[$va_matches[1]] = $va_item['text'];
             unset($va_item_info[$vn_key]);
             continue;
         }
         // if returned value is null then we skip the item
         if (is_null($va_plugin_item = $this->opo_app_plugin_manager->hookExportItem(array('instance' => $t_instance, 'exporter_item_instance' => $t_exporter_item, 'export_item' => $va_item)))) {
             continue;
         } else {
             $va_item = $va_plugin_item['export_item'];
         }
     }
     $o_log->logInfo(_t("Extracted data for this mapping is as follows:"));
     foreach ($va_item_info as $va_tmp) {
         $o_log->logInfo(sprintf("    element:%-20s value: %-10s", $va_tmp['element'], $va_tmp['text']));
     }
     $va_children = $t_exporter_item->getHierarchyChildren();
     if (is_array($va_children) && sizeof($va_children) > 0) {
         $o_log->logInfo(_t("Now proceeding to process %1 direct children in the mapping hierarchy", sizeof($va_children)));
         foreach ($va_children as $va_child) {
             foreach ($va_item_info as &$va_info) {
                 $va_child_export = $this->processExporterItem($va_child['item_id'], $pn_table_num, $pn_record_id, $pa_options);
                 $va_info['children'] = array_merge((array) $va_info['children'], $va_child_export);
             }
         }
     }
     return $va_item_info;
 }