Example #1
0
/**
 * Merges types specified with any specified "restrict_to_types"/"restrictToTypes" option, user access settings and types configured in app.conf
 * into a single list of type_ids suitable for enforcing type restrictions.
 *
 * @param BaseModel $t_instance A model instance for the table to which the types apply
 * @param array $pa_options An array of options containing, if specified, a list of types for either the "restrict_to_types" or "restrictToTypes" keys
 * 
 * @return array List of numeric type_ids for which the user has access
 */
function caMergeTypeRestrictionLists($t_instance, $pa_options)
{
    $va_restrict_to_type_ids = null;
    if (is_array($pa_options['restrict_to_types']) && sizeof($pa_options['restrict_to_types'])) {
        $pa_options['restrictToTypes'] = $pa_options['restrict_to_types'];
    }
    if (is_array($pa_options['restrictToTypes']) && sizeof($pa_options['restrictToTypes'])) {
        $va_restrict_to_type_ids = caMakeTypeIDList($t_instance->tableName(), $pa_options['restrictToTypes'], array('noChildren' => true));
    }
    $va_types = null;
    $o_config = Configuration::load();
    if ((bool) $o_config->get('perform_type_access_checking') && method_exists($t_instance, 'getTypeFieldName') && ($vs_type_field_name = $t_instance->getTypeFieldName())) {
        $va_types = caGetTypeRestrictionsForUser($t_instance->tableName());
    }
    if (is_array($va_types) && sizeof($va_types) && is_array($va_restrict_to_type_ids) && sizeof($va_restrict_to_type_ids)) {
        if (sizeof($va_tmp = array_intersect($va_restrict_to_type_ids, $va_types))) {
            $va_types = $va_tmp;
        }
    } else {
        if (!is_array($va_types) || !sizeof($va_types)) {
            $va_types = $va_restrict_to_type_ids;
        }
    }
    return $va_types;
}
 /**
  * Saves the content of a form editing new or existing records. It returns the same form + status messages rendered into the current view, inherited from ActionController
  *
  * @param array $pa_options Array of options passed through to _initView and saveBundlesForScreen()
  */
 public function Save($pa_options = null)
 {
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     list($t_subject, $t_ui, $vn_parent_id, $vn_above_id) = $this->_initView(array_merge($pa_options, array('loadSubject' => true)));
     if (!$t_subject) {
         $this->postError(1220, _t('Invalid table %1', $this->ops_table_name), "BaseInterstitalController->Edit()");
         return false;
     }
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     //
     // Is record of correct type?
     //
     $va_restrict_to_types = null;
     if ($t_subject->getAppConfig()->get('perform_type_access_checking')) {
         $va_restrict_to_types = caGetTypeRestrictionsForUser($this->ops_table_name, array('access' => __CA_BUNDLE_ACCESS_EDIT__));
     }
     if (is_array($va_restrict_to_types) && !in_array($t_subject->get('type_id'), $va_restrict_to_types)) {
         $this->response->setRedirect($this->request->config->get('error_display_url') . '/n/2560?r=' . urlencode($this->request->getFullUrlPath()));
         return;
     }
     $pn_placement_id = $this->request->getParameter('placement_id', pInteger);
     // placement_id of bundle that launched interstitial editor
     $ps_primary_table = $this->request->getParameter('primary', pString);
     $pn_primary_id = $this->request->getParameter('primary_id', pInteger);
     // Make sure request isn't empty
     if (!sizeof($_POST)) {
         $va_response = array('status' => 20, 'id' => null, 'table' => $t_subject->tableName(), 'type_id' => null, 'display' => null, 'errors' => array(_t("Cannot save using empty request. Are you using a bookmark?") => _t("Cannot save using empty request. Are you using a bookmark?")));
         $this->view->setVar('response', $va_response);
         $this->render('interstitial/interstitial_result_json.php');
         return;
     }
     // Set type name for display
     if (!($vs_type_name = $t_subject->getTypeName())) {
         $vs_type_name = $t_subject->getProperty('NAME_SINGULAR');
     }
     # trigger "BeforeSaveItem" hook
     $this->opo_app_plugin_manager->hookBeforeSaveItem(array('id' => null, 'table_num' => $t_subject->tableNum(), 'table_name' => $t_subject->tableName(), 'instance' => $t_subject, 'is_insert' => true));
     $t_placement = new ca_editor_ui_bundle_placements($pn_placement_id);
     $pa_bundle_settings = $t_placement->getSettings();
     $va_opts = array_merge($pa_options, array('ui_instance' => $t_ui));
     $vb_save_rc = $t_subject->saveBundlesForScreen($this->request->getParameter('screen', pString), $this->request, $va_opts);
     $this->view->setVar('t_ui', $t_ui);
     $vs_message = _t("Saved changes to %1", $vs_type_name);
     //
     // Regenerate display template for bundle that launched the interstitial editor so it will reflect any changes
     //
     $vs_related_table = $t_placement->getEditorType();
     $vs_template = caGetBundleDisplayTemplate($t_subject, $vs_related_table, $pa_bundle_settings);
     $qr_rel_items = caMakeSearchResult($t_subject->tableName(), array($t_subject->getPrimaryKey()));
     //
     // Handle case of self relationships where we need to figure out which direction things are going in
     //
     $va_bundle_values = array_shift(caProcessRelationshipLookupLabel($qr_rel_items, $t_subject, array('template' => $vs_template, 'primaryIDs' => array($ps_primary_table => array($pn_primary_id)))));
     if ($t_subject->hasField('type_id')) {
         if (method_exists($t_subject, "isSelfRelationship") && $t_subject->isSelfRelationship()) {
             $vn_left_id = $t_subject->get($t_subject->getLeftTableFieldName());
             $vn_right_id = $t_subject->get($t_subject->getRightTableFieldName());
             $va_bundle_values['relationship_typename'] = $t_subject->getRelationshipTypename($vn_left_id == $pn_primary_id ? 'ltol' : 'rtol');
         } else {
             $va_bundle_values['relationship_typename'] = $t_subject->getRelationshipTypename($t_subject->getLeftTableFieldName() == $vs_related_table ? 'rtol' : 'ltor');
         }
         $va_bundle_values['relationship_type_code'] = $t_subject->getRelationshipTypeCode();
     }
     //
     // Report errors
     //
     $va_errors = $this->request->getActionErrors();
     // all errors from all sources
     $va_general_errors = $this->request->getActionErrors('general');
     // just "general" errors - ones that are not attached to a specific part of the form
     if (sizeof($va_errors) - sizeof($va_general_errors) > 0) {
         $va_error_list = array();
         $vb_no_save_error = false;
         foreach ($va_errors as $o_e) {
             $va_error_list[$o_e->getErrorDescription()] = $o_e->getErrorDescription() . "\n";
             switch ($o_e->getErrorNumber()) {
                 case 1100:
                     // duplicate/invalid idno
                     if (!$vn_subject_id) {
                         // can't save new record if idno is not valid (when updating everything but idno is saved if it is invalid)
                         $vb_no_save_error = true;
                     }
                     break;
             }
         }
     } else {
         $this->opo_result_context->invalidateCache();
     }
     $this->opo_result_context->saveContext();
     # trigger "SaveItem" hook
     $this->opo_app_plugin_manager->hookSaveItem(array('id' => $vn_subject_id, 'table_num' => $t_subject->tableNum(), 'table_name' => $t_subject->tableName(), 'instance' => $t_subject, 'is_insert' => true));
     $vn_id = $t_subject->getPrimaryKey();
     $va_response = array('status' => sizeof($va_error_list) ? 10 : 0, 'id' => $vn_id, 'table' => $t_subject->tableName(), 'type_id' => method_exists($t_subject, "getTypeID") ? $t_subject->getTypeID() : null, 'display' => 'relation', 'bundleDisplay' => $va_bundle_values, 'errors' => $va_error_list);
     $this->view->setVar('response', $va_response);
     $this->render('interstitial/interstitial_result_json.php');
 }
 public function _genTypeNav($pa_params)
 {
     $t_subject = $this->opo_datamodel->getInstanceByTableName($this->ops_tablename, true);
     $t_list = new ca_lists();
     $t_list->load(array('list_code' => $t_subject->getTypeListCode()));
     $t_list_item = new ca_list_items();
     $t_list_item->load(array('list_id' => $t_list->getPrimaryKey(), 'parent_id' => null));
     $va_hier = caExtractValuesByUserLocale($t_list_item->getHierarchyWithLabels());
     $va_restrict_to_types = null;
     if ($t_subject->getAppConfig()->get('perform_type_access_checking')) {
         $va_restrict_to_types = caGetTypeRestrictionsForUser($this->ops_tablename, array('access' => __CA_BUNDLE_ACCESS_READONLY__));
     }
     $va_types = array();
     if (is_array($va_hier)) {
         $va_types_by_parent_id = array();
         $vn_root_id = $t_list->getRootItemIDForList($t_subject->getTypeListCode());
         // organize items by parent id, exclude root
         foreach ($va_hier as $vn_item_id => $va_item) {
             if ($vn_item_id == $vn_root_id) {
                 continue;
             }
             // skip root
             if (is_array($va_restrict_to_types) && !in_array($vn_item_id, $va_restrict_to_types)) {
                 continue;
             }
             $va_types_by_parent_id[$va_item['parent_id']][] = $va_item;
         }
         foreach ($va_hier as $vn_item_id => $va_item) {
             if (is_array($va_restrict_to_types) && !in_array($vn_item_id, $va_restrict_to_types)) {
                 continue;
             }
             if ($va_item['parent_id'] != $vn_root_id) {
                 continue;
             }
             // does this item have sub-items?
             if (isset($va_item['item_id']) && isset($va_types_by_parent_id[$va_item['item_id']]) && is_array($va_types_by_parent_id[$va_item['item_id']])) {
                 $va_subtypes = $this->_getSubTypes($va_types_by_parent_id[$va_item['item_id']], $va_types_by_parent_id, $va_restrict_to_types);
             } else {
                 $va_subtypes = array();
             }
             $va_types[] = array('displayName' => $va_item['name_plural'], 'parameters' => array('type_id' => $va_item['item_id']), 'is_enabled' => $va_item['is_enabled'], 'navigation' => $va_subtypes);
         }
     }
     return $va_types;
 }
 /**
  * Saves the content of a form editing new or existing records. It returns the same form + status messages rendered into the current view, inherited from ActionController
  *
  * @param array $pa_options Array of options passed through to _initView and saveBundlesForScreen()
  */
 public function Save($pa_options = null)
 {
     list($t_subject, $t_ui, $vn_parent_id, $vn_above_id) = $this->_initView($pa_options);
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     //
     // Is record of correct type?
     //
     $va_restrict_to_types = null;
     if ($t_subject->getAppConfig()->get('perform_type_access_checking')) {
         $va_restrict_to_types = caGetTypeRestrictionsForUser($this->ops_table_name, array('access' => __CA_BUNDLE_ACCESS_EDIT__));
     }
     if (is_array($va_restrict_to_types) && !in_array($t_subject->get('type_id'), $va_restrict_to_types)) {
         $this->response->setRedirect($this->request->config->get('error_display_url') . '/n/2560?r=' . urlencode($this->request->getFullUrlPath()));
         return;
     }
     // Make sure request isn't empty
     if (!sizeof($_POST)) {
         $va_response = array('status' => 20, 'id' => null, 'table' => $t_subject->tableName(), 'type_id' => null, 'display' => null, 'errors' => array(_t("Cannot save using empty request. Are you using a bookmark?") => _t("Cannot save using empty request. Are you using a bookmark?")));
         $this->view->setVar('response', $va_response);
         $this->render('component_result_json.php');
         return;
     }
     // Set "context" id from those editors that need to restrict idno lookups to within the context of another field value (eg. idno's for ca_list_items are only unique within a given list_id)
     $vn_context_id = null;
     if ($vs_idno_context_field = $t_subject->getProperty('ID_NUMBERING_CONTEXT_FIELD')) {
         if ($vn_subject_id > 0) {
             $this->view->setVar('_context_id', $vn_context_id = $t_subject->get($vs_idno_context_field));
         } else {
             if ($vn_parent_id > 0) {
                 $t_parent = $this->opo_datamodel->getInstanceByTableName($this->ops_table_name);
                 if ($t_parent->load($vn_parent_id)) {
                     $this->view->setVar('_context_id', $vn_context_id = $t_parent->get($vs_idno_context_field));
                 }
             }
         }
         if ($vn_context_id) {
             $t_subject->set($vs_idno_context_field, $vn_context_id);
         }
     }
     // Set type name for display
     if (!($vs_type_name = $t_subject->getTypeName())) {
         $vs_type_name = $t_subject->getProperty('NAME_SINGULAR');
     }
     # trigger "BeforeSaveItem" hook
     $this->opo_app_plugin_manager->hookBeforeSaveItem(array('id' => null, 'table_num' => $t_subject->tableNum(), 'table_name' => $t_subject->tableName(), 'instance' => $t_subject, 'is_insert' => true));
     $vn_parent_id = $this->request->getParameter('parent_id', pInteger);
     $t_subject->set('parent_id', $vn_parent_id);
     $this->opo_result_context->setParameter($t_subject->tableName() . '_last_parent_id', $vn_parent_id);
     $va_opts = array_merge($pa_options, array('ui_instance' => $t_ui));
     $vb_save_rc = $t_subject->saveBundlesForScreen($this->request->getParameter('screen', pString), $this->request, $va_opts);
     $this->view->setVar('t_ui', $t_ui);
     if (!$vn_subject_id) {
         $vn_subject_id = $t_subject->getPrimaryKey();
         if (!$vb_save_rc) {
             $vs_message = _t("Could not save %1", $vs_type_name);
         } else {
             $vs_message = _t("Added %1", $vs_type_name);
             $this->request->setParameter($t_subject->primaryKey(), $vn_subject_id, 'GET');
             $this->view->setVar($t_subject->primaryKey(), $vn_subject_id);
             $this->view->setVar('subject_id', $vn_subject_id);
             $this->request->session->setVar($this->ops_table_name . '_browse_last_id', $vn_subject_id);
             // set last edited
             // Set ACL for newly created record
             if ($t_subject->getAppConfig()->get('perform_item_level_access_checking')) {
                 $t_subject->setACLUsers(array($this->request->getUserID() => __CA_ACL_EDIT_DELETE_ACCESS__));
                 $t_subject->setACLWorldAccess($t_subject->getAppConfig()->get('default_item_access_level'));
             }
         }
     } else {
         $vs_message = _t("Saved changes to %1", $vs_type_name);
     }
     $va_errors = $this->request->getActionErrors();
     // all errors from all sources
     $va_general_errors = $this->request->getActionErrors('general');
     // just "general" errors - ones that are not attached to a specific part of the form
     if (sizeof($va_errors) - sizeof($va_general_errors) > 0) {
         $va_error_list = array();
         $vb_no_save_error = false;
         foreach ($va_errors as $o_e) {
             $va_error_list[$o_e->getErrorDescription()] = $o_e->getErrorDescription() . "\n";
             switch ($o_e->getErrorNumber()) {
                 case 1100:
                     // duplicate/invalid idno
                     if (!$vn_subject_id) {
                         // can't save new record if idno is not valid (when updating everything but idno is saved if it is invalid)
                         $vb_no_save_error = true;
                     }
                     break;
             }
         }
     } else {
         $this->opo_result_context->invalidateCache();
     }
     $this->opo_result_context->saveContext();
     # trigger "SaveItem" hook
     $this->opo_app_plugin_manager->hookSaveItem(array('id' => $vn_subject_id, 'table_num' => $t_subject->tableNum(), 'table_name' => $t_subject->tableName(), 'instance' => $t_subject, 'is_insert' => true));
     $vn_id = $t_subject->getPrimaryKey();
     if ($vn_id) {
         $va_tmp = caProcessRelationshipLookupLabel($t_subject->makeSearchResult($t_subject->tableName(), array($vn_id)), $t_subject);
         $va_name = array_pop($va_tmp);
     } else {
         $va_name = array();
     }
     $va_response = array('status' => sizeof($va_error_list) ? 10 : 0, 'id' => $vn_id, 'table' => $t_subject->tableName(), 'type_id' => method_exists($t_subject, "getTypeID") ? $t_subject->getTypeID() : null, 'display' => $va_name['label'], 'errors' => $va_error_list);
     $this->view->setVar('response', $va_response);
     $this->render('component_result_json.php');
 }
Example #5
0
 /**
  * Returns list of type_id values to restrict browse to. Return values are always numeric types, 
  * never codes, and will include all type_ids to filter on, including children of hierarchical types.
  *
  * @return array List of type_id values to restrict browse to.
  */
 public function getTypeRestrictionList()
 {
     if (function_exists("caGetTypeRestrictionsForUser")) {
         $va_pervasive_types = caGetTypeRestrictionsForUser($this->ops_tablename);
         // restrictions set in app.conf or by associated user role
         if (!is_array($va_pervasive_types) || !sizeof($va_pervasive_types)) {
             return $this->opa_browse_type_ids;
         }
         if (is_array($this->opa_browse_type_ids) && sizeof($this->opa_browse_type_ids)) {
             $va_filtered_types = array();
             foreach ($this->opa_browse_type_ids as $vn_id) {
                 if (in_array($vn_id, $va_pervasive_types)) {
                     $va_filtered_types[] = $vn_id;
                 }
             }
             return $va_filtered_types;
         } else {
             return $va_pervasive_types;
         }
     }
     return $this->opa_browse_type_ids;
 }
Example #6
0
 /**
  * Performs the quickest possible search on the index for the table specified by the superclass
  * using the text in $ps_search. Unlike the search() method, quickSearch doesn't support
  * any sort of search syntax. You give it some text and you get a collection of (hopefully) relevant results back quickly. 
  * quickSearch() is intended for autocompleting search suggestion UI's and the like, where performance is critical
  * and the ability to control search parameters is not required.
  *
  * Quick searches are NOT logged to ca_search_log
  *
  * @param $ps_search - The text to search on
  * @param $ps_tablename - name of table to search on
  * @param $pn_table_num - number of table to search on (same table as $ps_tablename)
  * @param $pa_options - an optional associative array specifying search options. Supported options are: 'limit' (the maximum number of results to return), 'checkAccess' (only return results that have an access value = to the specified value)
  * 
  * @return Array - an array of results is returned keys first by primary key id, then by locale_id. The array values are associative arrays with two keys: type_id (the type_id of the result; this points to a ca_list_items row defining the type of the result item) and label (the row item's label display field). You can push the returned results array from caExtractValuesByUserLocale() to get an array keyed by primary key id and returning for each id a displayable text label + the type of the found result item.
  * 
  */
 static function quickSearch($ps_search, $ps_tablename, $pn_tablenum, $pa_options = null)
 {
     $o_config = Configuration::load();
     $o_dm = Datamodel::load();
     if (!($ps_plugin_name = $o_config->get('search_engine_plugin'))) {
         return null;
     }
     if (!@(require_once __CA_LIB_DIR__ . '/core/Plugins/SearchEngine/' . $ps_plugin_name . '.php')) {
         return null;
     }
     $ps_classname = 'WLPlugSearchEngine' . $ps_plugin_name;
     if (!($o_engine = new $ps_classname())) {
         return null;
     }
     $va_ids = $o_engine->quickSearch($pn_tablenum, $ps_search, $pa_options);
     if (!is_array($va_ids) || !sizeof($va_ids)) {
         return array();
     }
     $t_instance = $o_dm->getInstanceByTableNum($pn_tablenum, true);
     $t_label_instance = $t_instance->getLabelTableInstance();
     $vs_label_table_name = $t_instance->getLabelTableName();
     $vs_label_display_field = $t_instance->getLabelDisplayField();
     $vs_pk = $t_instance->primaryKey();
     $vs_is_preferred_sql = '';
     if ($t_label_instance->hasField('is_preferred')) {
         $vs_is_preferred_sql = ' AND (l.is_preferred = 1)';
     }
     $vs_check_access_sql = '';
     if (isset($pa_options['checkAccess']) && is_array($pa_options['checkAccess']) && sizeof($pa_options['checkAccess']) && $t_instance->hasField('access')) {
         $vs_check_access_sql = ' AND (n.access IN (' . join(", ", $pa_options['checkAccess']) . '))';
     }
     $vs_limit_sql = '';
     if (isset($pa_options['limit']) && !is_null($pa_options['limit']) && $pa_options['limit'] > 0) {
         $vs_limit_sql = ' LIMIT ' . intval($pa_options['limit']);
     }
     $vs_type_restriction_sql = '';
     $va_types = caGetTypeRestrictionsForUser($ps_tablename);
     if (is_array($va_types) && sizeof($va_types)) {
         $vs_type_restriction_sql = ' AND n.type_id IN (' . join(',', $va_types) . ')';
     }
     $vs_delete_sql = '';
     if ($t_instance->hasField('deleted')) {
         $vs_delete_sql = ' AND (deleted = 0)';
     }
     $o_db = new Db();
     $qr_res = $o_db->query("\n\t\t\tSELECT n.{$vs_pk}, l.{$vs_label_display_field}, l.locale_id, n.type_id\n\t\t\tFROM {$vs_label_table_name} l\n\t\t\tINNER JOIN " . $ps_tablename . " AS n ON n.{$vs_pk} = l.{$vs_pk}\n\t\t\tWHERE\n\t\t\t\tl." . $vs_pk . " IN (" . join(',', $va_ids) . ")\n\t\t\t\t{$vs_is_preferred_sql}\n\t\t\t\t{$vs_check_access_sql}\n\t\t\t\t{$vs_type_restriction_sql}\n\t\t\t\t{$vs_delete_sql}\n\t\t\t{$vs_limit_sql}\n\t\t");
     $va_hits = array();
     while ($qr_res->nextRow()) {
         $va_hits[$qr_res->get($vs_pk)][$qr_res->get('locale_id')] = array('type_id' => $qr_res->get('type_id'), 'label' => $qr_res->get($vs_label_display_field));
     }
     return $va_hits;
 }
 /**
  * Saves the content of a form editing new or existing records. It returns the same form + status messages rendered into the current view, inherited from ActionController
  *
  * @param array $pa_options Array of options passed through to _initView and saveBundlesForScreen()
  */
 public function Save($pa_options = null)
 {
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     list($t_subject, $t_ui, $vn_parent_id, $vn_above_id) = $this->_initView(array_merge($pa_options, array('loadSubject' => true)));
     if (!$t_subject) {
         $this->postError(1220, _t('Invalid table %1', $this->ops_table_name), "BaseInterstitalController->Edit()");
         return false;
     }
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     //
     // Is record of correct type?
     //
     $va_restrict_to_types = null;
     if ($t_subject->getAppConfig()->get('perform_type_access_checking')) {
         $va_restrict_to_types = caGetTypeRestrictionsForUser($this->ops_table_name, array('access' => __CA_BUNDLE_ACCESS_EDIT__));
     }
     if (is_array($va_restrict_to_types) && !in_array($t_subject->get('type_id'), $va_restrict_to_types)) {
         $this->response->setRedirect($this->request->config->get('error_display_url') . '/n/2560?r=' . urlencode($this->request->getFullUrlPath()));
         return;
     }
     // Make sure request isn't empty
     if (!sizeof($_POST)) {
         $va_response = array('status' => 20, 'id' => null, 'table' => $t_subject->tableName(), 'type_id' => null, 'display' => null, 'errors' => array(_t("Cannot save using empty request. Are you using a bookmark?") => _t("Cannot save using empty request. Are you using a bookmark?")));
         $this->view->setVar('response', $va_response);
         $this->render('interstitial/interstitial_result_json.php');
         return;
     }
     // Set type name for display
     if (!($vs_type_name = $t_subject->getTypeName())) {
         $vs_type_name = $t_subject->getProperty('NAME_SINGULAR');
     }
     # trigger "BeforeSaveItem" hook
     $this->opo_app_plugin_manager->hookBeforeSaveItem(array('id' => null, 'table_num' => $t_subject->tableNum(), 'table_name' => $t_subject->tableName(), 'instance' => $t_subject, 'is_insert' => true));
     $va_opts = array_merge($pa_options, array('ui_instance' => $t_ui));
     $vb_save_rc = $t_subject->saveBundlesForScreen($this->request->getParameter('screen', pString), $this->request, $va_opts);
     $this->view->setVar('t_ui', $t_ui);
     $vs_message = _t("Saved changes to %1", $vs_type_name);
     $va_errors = $this->request->getActionErrors();
     // all errors from all sources
     $va_general_errors = $this->request->getActionErrors('general');
     // just "general" errors - ones that are not attached to a specific part of the form
     if (sizeof($va_errors) - sizeof($va_general_errors) > 0) {
         $va_error_list = array();
         $vb_no_save_error = false;
         foreach ($va_errors as $o_e) {
             $va_error_list[$o_e->getErrorDescription()] = $o_e->getErrorDescription() . "\n";
             switch ($o_e->getErrorNumber()) {
                 case 1100:
                     // duplicate/invalid idno
                     if (!$vn_subject_id) {
                         // can't save new record if idno is not valid (when updating everything but idno is saved if it is invalid)
                         $vb_no_save_error = true;
                     }
                     break;
             }
         }
     } else {
         $this->opo_result_context->invalidateCache();
     }
     $this->opo_result_context->saveContext();
     # trigger "SaveItem" hook
     $this->opo_app_plugin_manager->hookSaveItem(array('id' => $vn_subject_id, 'table_num' => $t_subject->tableNum(), 'table_name' => $t_subject->tableName(), 'instance' => $t_subject, 'is_insert' => true));
     $vn_id = $t_subject->getPrimaryKey();
     $va_response = array('status' => sizeof($va_error_list) ? 10 : 0, 'id' => $vn_id, 'table' => $t_subject->tableName(), 'type_id' => method_exists($t_subject, "getTypeID") ? $t_subject->getTypeID() : null, 'display' => 'relation', 'errors' => $va_error_list);
     $this->view->setVar('response', $va_response);
     $this->render('interstitial/interstitial_result_json.php');
 }
 /**
  * Returns HTML <select> form element with type list
  *
  * @param string $ps_name The name of the returned form element
  * @param array $pa_attributes An optional array of HTML attributes to place into the returned <select> tag
  * @param array $pa_options An array of options. Supported options are anything supported by ca_lists::getListAsHTMLFormElement as well as:
  *		childrenOfCurrentTypeOnly = Returns only types below the current type
  *		restrictToTypes = Array of type_ids to restrict type list to
  * @return string HTML for list element
  */
 public function getTypeListAsHTMLFormElement($ps_name, $pa_attributes = null, $pa_options = null)
 {
     $t_list = new ca_lists();
     if (isset($pa_options['childrenOfCurrentTypeOnly']) && $pa_options['childrenOfCurrentTypeOnly']) {
         $pa_options['childrenOnlyForItemID'] = $this->get('type_id');
     }
     $pa_options['limitToItemsWithID'] = caGetTypeRestrictionsForUser($this->tableName(), $pa_options);
     if (isset($pa_options['restrictToTypes']) && is_array($pa_options['restrictToTypes'])) {
         $pa_options['restrictToTypes'] = caMakeTypeIDList($this->tableName(), $pa_options['restrictToTypes'], $pa_options);
         if (!$pa_options['limitToItemsWithID'] || !is_array($pa_options['limitToItemsWithID'])) {
             $pa_options['limitToItemsWithID'] = $pa_options['restrictToTypes'];
         } else {
             $pa_options['limitToItemsWithID'] = array_intersect($pa_options['limitToItemsWithID'], $pa_options['restrictToTypes']);
         }
     }
     return $t_list->getListAsHTMLFormElement($this->getTypeListCode(), $ps_name, $pa_attributes, $pa_options);
 }
 /**
  * Called just after record is deleted. Individual editor controllers can override this to implement their
  * own post-deletion cleanup logic.
  *
  * @param BaseModel $pt_subject Model instance of row that was deleted
  * @return bool True if post-deletion cleanup was successful, false if not
  */
 protected function _checkAccess($pt_subject, $pa_options = null)
 {
     //
     // Is record deleted?
     //
     if ($pt_subject->hasField('deleted') && $pt_subject->get('deleted')) {
         if (!caGetOption('dontRedirectOnDelete', $pa_options, false)) {
             $this->response->setRedirect($this->request->config->get('error_display_url') . '/n/2550?r=' . urlencode($this->request->getFullUrlPath()));
         }
         return false;
     }
     //
     // Is record of correct type?
     //
     $va_restrict_to_types = null;
     if ($pt_subject->getAppConfig()->get('perform_type_access_checking')) {
         $va_restrict_to_types = caGetTypeRestrictionsForUser($this->ops_table_name, array('access' => __CA_BUNDLE_ACCESS_READONLY__));
     }
     if (is_array($va_restrict_to_types) && ($pt_subject->get('type_id') && ($pt_subject->getPrimaryKey() && !in_array($pt_subject->get('type_id'), $va_restrict_to_types)))) {
         $this->response->setRedirect($this->request->config->get('error_display_url') . '/n/2560?r=' . urlencode($this->request->getFullUrlPath()));
         return false;
     }
     //
     // Is record from correct source?
     //
     $va_restrict_to_sources = null;
     if ($pt_subject->getAppConfig()->get('perform_source_access_checking') && $pt_subject->hasField('source_id')) {
         if (is_array($va_restrict_to_sources = caGetSourceRestrictionsForUser($this->ops_table_name, array('access' => __CA_BUNDLE_ACCESS_READONLY__)))) {
             if (!$pt_subject->get('source_id') || $pt_subject->get('source_id') && !in_array($pt_subject->get('source_id'), $va_restrict_to_sources) || strlen($vn_source_id = $this->request->getParameter('source_id', pInteger)) && !in_array($vn_source_id, $va_restrict_to_sources)) {
                 $pt_subject->set('source_id', $pt_subject->getDefaultSourceID(array('request' => $this->request)));
             }
             if (is_array($va_restrict_to_sources) && !in_array($pt_subject->get('source_id'), $va_restrict_to_sources)) {
                 $this->response->setRedirect($this->request->config->get('error_display_url') . '/n/2562?r=' . urlencode($this->request->getFullUrlPath()));
                 return;
             }
         }
     }
     //
     // Does user have access to row?
     //
     if ($pt_subject->getAppConfig()->get('perform_item_level_access_checking') && $vn_subject_id) {
         if ($pt_subject->checkACLAccessForUser($this->request->user) < __CA_BUNDLE_ACCESS_READONLY__) {
             $this->response->setRedirect($this->request->config->get('error_display_url') . '/n/2580?r=' . urlencode($this->request->getFullUrlPath()));
             return false;
         }
     }
     return true;
 }
 /**
  * Returns navigation fragment for types and subtypes of a given primary item type (Eg. ca_objects). Used to generate dynamic type menus 
  * from database by AppNavigation class. 
  *
  * @param array $pa_params Array of parameters used to generate menu
  * @return array List of types with subtypes ready for inclusion in a menu spec
  */
 public function _genTypeNav($pa_params)
 {
     $t_subject = $this->opo_datamodel->getInstanceByTableName($this->ops_table_name, true);
     $t_list = new ca_lists();
     $t_list->load(array('list_code' => $t_subject->getTypeListCode()));
     $t_list_item = new ca_list_items();
     $t_list_item->load(array('list_id' => $t_list->getPrimaryKey(), 'parent_id' => null));
     $va_hier = caExtractValuesByUserLocale($t_list_item->getHierarchyWithLabels());
     $vn_sort_type = $t_list->get('default_sort');
     $va_restrict_to_types = null;
     if ($t_subject->getAppConfig()->get('perform_type_access_checking')) {
         $va_restrict_to_types = caGetTypeRestrictionsForUser($this->ops_table_name, array('access' => __CA_BUNDLE_ACCESS_EDIT__));
     }
     $va_types = array();
     if (is_array($va_hier)) {
         $va_types_by_parent_id = array();
         $vn_root_id = $t_list->getRootItemIDForList($t_subject->getTypeListCode());
         foreach ($va_hier as $vn_item_id => $va_item) {
             if ($vn_item_id == $vn_root_id) {
                 continue;
             }
             // skip root
             $va_types_by_parent_id[$va_item['parent_id']][] = $va_item;
         }
         foreach ($va_hier as $vn_item_id => $va_item) {
             if (is_array($va_restrict_to_types) && !in_array($vn_item_id, $va_restrict_to_types)) {
                 continue;
             }
             if ($va_item['parent_id'] != $vn_root_id) {
                 continue;
             }
             // does this item have sub-items?
             $va_subtypes = array();
             if (!(bool) $this->getRequest()->config->get($this->ops_table_name . '_navigation_new_menu_shows_top_level_types_only') && !(bool) $this->getRequest()->config->get($this->ops_table_name . '_enforce_strict_type_hierarchy')) {
                 if (isset($va_item['item_id']) && isset($va_types_by_parent_id[$va_item['item_id']]) && is_array($va_types_by_parent_id[$va_item['item_id']])) {
                     $va_subtypes = $this->_getSubTypes($va_types_by_parent_id[$va_item['item_id']], $va_types_by_parent_id, $vn_sort_type, $va_restrict_to_types);
                 }
             }
             switch ($vn_sort_type) {
                 case 0:
                     // label
                 // label
                 default:
                     $vs_key = $va_item['name_singular'];
                     break;
                 case 1:
                     // rank
                     $vs_key = sprintf("%08d", (int) $va_item['rank']);
                     break;
                 case 2:
                     // value
                     $vs_key = $va_item['item_value'];
                     break;
                 case 3:
                     // identifier
                     $vs_key = $va_item['idno_sort'];
                     break;
             }
             $va_types[$vs_key][] = array('displayName' => $va_item['name_singular'], 'parameters' => array('type_id' => $va_item['item_id']), 'is_enabled' => $va_item['is_enabled'], 'navigation' => $va_subtypes);
         }
         ksort($va_types);
     }
     $va_types_proc = array();
     foreach ($va_types as $vs_sort_key => $va_items) {
         foreach ($va_items as $vn_i => $va_item) {
             $va_types_proc[] = $va_item;
         }
     }
     return $va_types_proc;
 }
 /**
  * @param array $pa_options
  *		progressCallback =
  *		reportCallback =
  */
 public static function changeTypeBatchForSet($po_request, $pn_type_id, $t_set, $t_subject, $pa_options = null)
 {
     $va_row_ids = $t_set->getItemRowIDs();
     $vn_num_items = sizeof($va_row_ids);
     if (!method_exists($t_subject, 'getTypeList')) {
         return array('errors' => array(_t('Invalid subject')), 'notices' => array(), 'processing_time' => caFormatInterval(0));
     }
     $va_type_list = $t_subject->getTypeList();
     if (!isset($va_type_list[$pn_type_id])) {
         return array('errors' => array(_t('Invalid type_id')), 'notices' => array(), 'processing_time' => caFormatInterval(0));
     }
     $va_notices = $va_errors = array();
     if ($vb_perform_type_access_checking = (bool) $t_subject->getAppConfig()->get('perform_type_access_checking')) {
         $va_restrict_to_types = caGetTypeRestrictionsForUser($t_subject->tableName(), array('access' => __CA_BUNDLE_ACCESS_EDIT__));
     }
     $vb_perform_item_level_access_checking = (bool) $t_subject->getAppConfig()->get('perform_item_level_access_checking');
     $vb_we_set_transaction = false;
     $o_tx = caGetOption('transaction', $pa_options);
     if (!$o_tx) {
         $vb_we_set_transaction = true;
         $o_db = new Db();
         // open up a new connection?
         $o_tx = new Transaction($o_db);
     }
     $t_subject->setTransaction($o_tx);
     $t_subject->setMode(ACCESS_WRITE);
     $o_log = new Batchlog(array('user_id' => $po_request->getUserID(), 'batch_type' => 'TC', 'table_num' => (int) $t_set->get('table_num'), 'notes' => '', 'transaction' => $o_tx));
     $vn_c = 0;
     $vn_start_time = time();
     foreach (array_keys($va_row_ids) as $vn_row_id) {
         if ($t_subject->load($vn_row_id)) {
             // Is record deleted?
             if ($t_subject->hasField('deleted') && $t_subject->get('deleted')) {
                 continue;
                 // skip
             }
             // Is record of correct type?
             if ($vb_perform_type_access_checking && (is_array($va_restrict_to_types) && !in_array($t_subject->get('type_id'), $va_restrict_to_types))) {
                 continue;
                 // skip
             }
             // Does user have access to row?
             if ($vb_perform_item_level_access_checking && $t_subject->checkACLAccessForUser($po_request->user) == __CA_ACL_READ_WRITE_ACCESS__) {
                 continue;
                 // skip
             }
             // get some data for reporting before delete
             $vs_label = $t_subject->getLabelForDisplay();
             $vs_idno = $t_subject->get($t_subject->getProperty('ID_NUMBERING_ID_FIELD'));
             $t_subject->set('type_id', $pn_type_id, array('allowSettingOfTypeID' => true));
             $t_subject->update();
             $o_log->addItem($vn_row_id, $va_record_errors = $t_subject->errors());
             if (sizeof($va_record_errors) > 0) {
                 $va_errors[$vn_row_id] = array('idno' => $vs_idno, 'label' => $vs_label, 'errors' => $va_record_errors, 'status' => 'ERROR');
             } else {
                 $va_notices[$vn_row_id] = array('idno' => $vs_idno, 'label' => $vs_label, 'status' => 'SUCCESS');
             }
             if (isset($pa_options['progressCallback']) && ($ps_callback = $pa_options['progressCallback'])) {
                 $ps_callback($po_request, $vn_c, $vn_num_items, _t("[%3/%4] Processing %1 (%2)", caTruncateStringWithEllipsis($vs_label, 50), $vs_idno, $vn_c, $vn_num_items), time() - $vn_start_time, memory_get_usage(true), sizeof($va_notices), sizeof($va_errors));
             }
             $vn_c++;
         }
     }
     if (isset($pa_options['progressCallback']) && ($ps_callback = $pa_options['progressCallback'])) {
         $ps_callback($po_request, $vn_num_items, $vn_num_items, _t("Processing completed"), time() - $vn_start_time, memory_get_usage(true), sizeof($va_notices), sizeof($va_errors));
     }
     $vn_elapsed_time = time() - $vn_start_time;
     if (isset($pa_options['reportCallback']) && ($ps_callback = $pa_options['reportCallback'])) {
         $va_general = array('elapsedTime' => $vn_elapsed_time, 'numErrors' => sizeof($va_errors), 'numProcessed' => sizeof($va_notices), 'batchSize' => $vn_num_items, 'table' => $t_subject->tableName(), 'set_id' => $t_set->getPrimaryKey(), 'set_name' => $t_set->getLabelForDisplay());
         $ps_callback($po_request, $va_general, $va_notices, $va_errors);
     }
     $o_log->close();
     if ($vb_we_set_transaction) {
         if (sizeof($va_errors) > 0) {
             $o_tx->rollback();
         } else {
             $o_tx->commit();
         }
     }
     $vs_set_name = $t_set->getLabelForDisplay();
     $vs_started_on = caGetLocalizedDate($vn_start_time);
     return array('errors' => $va_errors, 'notices' => $va_notices, 'processing_time' => caFormatInterval($vn_elapsed_time));
 }
 /**
  * Returns HTML <select> form element with type list
  *
  * @param string $ps_name The name of the returned form element
  * @param array $pa_attributes An optional array of HTML attributes to place into the returned <select> tag
  * @param array $pa_options An array of options. Supported options are anything supported by ca_lists::getListAsHTMLFormElement as well as:
  *		childrenOfCurrentTypeOnly = Returns only types below the current type
  *		restrictToTypes = Array of type_ids to restrict type list to
  *		inUse = Return only types that are used by at least one record. [Default is false]
  *		checkAccess = Array of access values to filter returned values on. Available for any related table with an "access" field (ca_objects, ca_entities, etc.). If omitted no filtering is performed. [Default is null]
  * @return string HTML for list element
  */
 public function getTypeListAsHTMLFormElement($ps_name, $pa_attributes = null, $pa_options = null)
 {
     $t_list = new ca_lists();
     if (isset($pa_options['childrenOfCurrentTypeOnly']) && $pa_options['childrenOfCurrentTypeOnly']) {
         $pa_options['childrenOnlyForItemID'] = $this->get('type_id');
     }
     $pa_options['limitToItemsWithID'] = caGetTypeRestrictionsForUser($this->tableName(), $pa_options);
     if (caGetOption('inUse', $pa_options, false)) {
         $vs_access_sql = '';
         $va_sql_params = array();
         if (($va_check_access = caGetOption('checkAccess', $pa_options, null)) && is_array($va_check_access) && sizeof($va_check_access) && $this->hasField('access')) {
             array_walk($va_check_access, function (&$pm_item, $ps_key) {
                 $pm_item = (int) $pm_item;
             });
             $vs_access_sql = " AND (access IN (?))";
             $va_sql_params[] = $va_check_access;
             $qr_types_in_use = $this->getDb()->query("SELECT DISTINCT type_id FROM " . $this->tableName() . ($this->hasField('deleted') ? " WHERE deleted = 0 {$vs_access_sql}" : ""), $va_sql_params);
         }
         if (!is_array($pa_options['limitToItemsWithID'])) {
             $pa_options['limitToItemsWithID'] = array();
         }
         if ($qr_types_in_use->numRows() > 0) {
             $pa_options['limitToItemsWithID'] += $qr_types_in_use->getAllFieldValues('type_id');
         }
     }
     if (isset($pa_options['restrictToTypes']) && is_array($pa_options['restrictToTypes'])) {
         $pa_options['restrictToTypes'] = caMakeTypeIDList($this->tableName(), $pa_options['restrictToTypes'], $pa_options);
         if (!$pa_options['limitToItemsWithID'] || !is_array($pa_options['limitToItemsWithID'])) {
             $pa_options['limitToItemsWithID'] = $pa_options['restrictToTypes'];
         } else {
             $pa_options['limitToItemsWithID'] = array_intersect($pa_options['limitToItemsWithID'], $pa_options['restrictToTypes']);
         }
     }
     return $t_list->getListAsHTMLFormElement($this->getTypeListCode(), $ps_name, $pa_attributes, $pa_options);
 }
Example #13
0
 /**
  * @param array $pa_options
  *		progressCallback =
  *		reportCallback = 
  *		sendMail = 
  */
 public static function saveBatchEditorFormForSet($po_request, $t_set, $t_subject, $pa_options = null)
 {
     $va_row_ids = $t_set->getItemRowIDs();
     $vn_num_items = sizeof($va_row_ids);
     $va_notices = $va_errors = array();
     if ($vb_perform_type_access_checking = (bool) $t_subject->getAppConfig()->get('perform_type_access_checking')) {
         $va_restrict_to_types = caGetTypeRestrictionsForUser($t_subject->tableName(), array('access' => __CA_BUNDLE_ACCESS_EDIT__));
     }
     $vb_perform_item_level_access_checking = (bool) $t_subject->getAppConfig()->get('perform_item_level_access_checking');
     $vb_we_set_transaction = false;
     $o_trans = isset($pa_options['transaction']) && $pa_options['transaction'] ? $pa_options['transaction'] : null;
     if (!$o_trans) {
         $vb_we_set_transaction = true;
         $o_trans = new Transaction();
     }
     $o_log = new Batchlog(array('user_id' => $po_request->getUserID(), 'batch_type' => 'BE', 'table_num' => (int) $t_set->get('table_num'), 'notes' => '', 'transaction' => $o_trans));
     $vs_screen = $po_request->getActionExtra();
     $t_screen = new ca_editor_ui_screens(str_replace("Screen", "", $vs_screen));
     if ($t_screen->getPrimaryKey()) {
         $t_ui = new ca_editor_uis($t_screen->get('ui_id'));
     } else {
         $t_ui = null;
     }
     $va_save_opts = array('batch' => true, 'existingRepresentationMap' => array(), 'ui_instance' => $t_ui);
     $vn_c = 0;
     $vn_start_time = time();
     foreach (array_keys($va_row_ids) as $vn_row_id) {
         $t_subject->setTransaction($o_trans);
         if ($t_subject->load($vn_row_id)) {
             $po_request->clearActionErrors();
             //
             // Is record deleted?
             //
             if ($t_subject->hasField('deleted') && $t_subject->get('deleted')) {
                 continue;
                 // skip
             }
             //
             // Is record of correct type?
             //
             if ($vb_perform_type_access_checking && (is_array($va_restrict_to_types) && !in_array($t_subject->get('type_id'), $va_restrict_to_types))) {
                 continue;
                 // skip
             }
             //
             // Does user have access to row?
             //
             if ($vb_perform_item_level_access_checking && $t_subject->checkACLAccessForUser($po_request->user) == __CA_ACL_READ_WRITE_ACCESS__) {
                 continue;
                 // skip
             }
             // TODO: call plugins beforeBatchItemSave?
             $t_subject->saveBundlesForScreen($vs_screen, $po_request, $va_save_opts);
             // TODO: call plugins beforeAfterItemSave?
             $o_log->addItem($vn_row_id, $va_action_errors = $po_request->getActionErrors());
             if (sizeof($va_action_errors) > 0) {
                 $va_errors[$t_subject->getPrimaryKey()] = array('idno' => $t_subject->get($t_subject->getProperty('ID_NUMBERING_ID_FIELD')), 'label' => $t_subject->getLabelForDisplay(), 'errors' => $va_action_errors, 'status' => 'ERROR');
             } else {
                 $va_notices[$t_subject->getPrimaryKey()] = array('idno' => $t_subject->get($t_subject->getProperty('ID_NUMBERING_ID_FIELD')), 'label' => $t_subject->getLabelForDisplay(), 'status' => 'SUCCESS');
             }
             if (isset($pa_options['progressCallback']) && ($ps_callback = $pa_options['progressCallback'])) {
                 $ps_callback($po_request, $vn_c, $vn_num_items, _t("[%3/%4] Processing %1 (%2)", caTruncateStringWithEllipsis($t_subject->getLabelForDisplay(), 50), $t_subject->get($t_subject->getProperty('ID_NUMBERING_ID_FIELD')), $vn_c, $vn_num_items), time() - $vn_start_time, memory_get_usage(true), sizeof($va_notices), sizeof($va_errors));
             }
             $vn_c++;
         }
     }
     if (isset($pa_options['progressCallback']) && ($ps_callback = $pa_options['progressCallback'])) {
         $ps_callback($po_request, $vn_num_items, $vn_num_items, _t("Processing completed"), time() - $vn_start_time, memory_get_usage(true), sizeof($va_notices), sizeof($va_errors));
     }
     $vn_elapsed_time = time() - $vn_start_time;
     if (isset($pa_options['reportCallback']) && ($ps_callback = $pa_options['reportCallback'])) {
         $va_general = array('elapsedTime' => $vn_elapsed_time, 'numErrors' => sizeof($va_errors), 'numProcessed' => sizeof($va_notices), 'batchSize' => $vn_num_items, 'table' => $t_subject->tableName(), 'set_id' => $t_set->getPrimaryKey(), 'set_name' => $t_set->getLabelForDisplay());
         $ps_callback($po_request, $va_general, $va_notices, $va_errors);
     }
     $o_log->close();
     if ($vb_we_set_transaction) {
         if (sizeof($va_errors) > 0) {
             $o_trans->rollback();
         } else {
             $o_trans->commit();
         }
     }
     $vs_set_name = $t_set->getLabelForDisplay();
     $vs_started_on = caGetLocalizedDate($vn_start_time);
     if (isset($pa_options['sendMail']) && $pa_options['sendMail']) {
         if ($vs_email = trim($po_request->user->get('email'))) {
             caSendMessageUsingView($po_request, array($vs_email => $po_request->user->get('fname') . ' ' . $po_request->user->get('lname')), __CA_ADMIN_EMAIL__, _t('[%1] Batch edit completed', $po_request->config->get('app_display_name')), 'batch_processing_completed.tpl', array('notices' => $va_notices, 'errors' => $va_errors, 'batchSize' => $vn_num_items, 'numErrors' => sizeof($va_errors), 'numProcessed' => sizeof($va_notices), 'subjectNameSingular' => $t_subject->getProperty('NAME_SINGULAR'), 'subjectNamePlural' => $t_subject->getProperty('NAME_PLURAL'), 'startedOn' => $vs_started_on, 'completedOn' => caGetLocalizedDate(time()), 'setName' => $vs_set_name, 'elapsedTime' => caFormatInterval($vn_elapsed_time)));
         }
     }
     if (isset($pa_options['sendSMS']) && $pa_options['sendSMS']) {
         SMS::send($po_request->getUserID(), _t("[%1] Batch processing for set %2 with %3 %4 begun at %5 is complete", $po_request->config->get('app_display_name'), caTruncateStringWithEllipsis($vs_set_name, 20), $vn_num_items, $t_subject->getProperty($vn_num_items == 1 ? 'NAME_SINGULAR' : 'NAME_PLURAL'), $vs_started_on));
     }
     return array('errors' => $va_errors, 'notices' => $va_notices, 'processing_time' => caFormatInterval($vn_elapsed_time));
 }