public function processMetadataElements() { require_once __CA_MODELS_DIR__ . "/ca_lists.php"; require_once __CA_MODELS_DIR__ . "/ca_list_items.php"; require_once __CA_MODELS_DIR__ . "/ca_relationship_types.php"; $vo_dm = Datamodel::load(); $t_rel_types = new ca_relationship_types(); $t_list = new ca_lists(); $va_elements = array(); if ($this->ops_base_name) { // "merge" profile and its base foreach ($this->opo_base->elementSets->children() as $vo_element) { $va_elements[self::getAttribute($vo_element, "code")] = $vo_element; } foreach ($this->opo_profile->elementSets->children() as $vo_element) { $va_elements[self::getAttribute($vo_element, "code")] = $vo_element; } } else { foreach ($this->opo_profile->elementSets->children() as $vo_element) { $va_elements[self::getAttribute($vo_element, "code")] = $vo_element; } } foreach ($va_elements as $vs_element_code => $vo_element) { if ($vn_element_id = $this->processMetadataElement($vo_element, null)) { // handle restrictions foreach ($vo_element->typeRestrictions->children() as $vo_restriction) { $vs_restriction_code = self::getAttribute($vo_restriction, "code"); if (!($vn_table_num = $vo_dm->getTableNum((string) $vo_restriction->table))) { $this->addError("Invalid table specified for restriction {$vs_restriction_code} in element {$vs_element_code}"); return false; } $t_instance = $vo_dm->getTableInstance((string) $vo_restriction->table); $vn_type_id = null; $vs_type = trim((string) $vo_restriction->type); // is this restriction further restricted on a specific type? -> get real id from code if (strlen($vs_type) > 0) { // interstitial with type restriction -> code is relationship type code if ($t_instance instanceof BaseRelationshipModel) { $vn_type_id = $t_rel_types->getRelationshipTypeID($t_instance->tableName(), $vs_type); } else { // "normal" type restriction -> code is from actual type list $vs_type_list_name = $t_instance->getFieldListCode($t_instance->getTypeFieldName()); $vn_type_id = $t_list->getItemIDFromList($vs_type_list_name, $vs_type); } } // add restriction $t_restriction = $this->opb_updating ? ca_metadata_type_restrictions::find(array('table_num' => $vn_table_num, 'type_id' => $vn_type_id, 'element_id' => $vn_element_id), array('returnAs' => 'firstModelInstance')) : false; $t_restriction = $t_restriction ? $t_restriction : new ca_metadata_type_restrictions(); $t_restriction->setMode(ACCESS_WRITE); $t_restriction->set('table_num', $vn_table_num); $t_restriction->set('include_subtypes', (bool) $vo_restriction->includeSubtypes ? 1 : 0); $t_restriction->set('type_id', $vn_type_id); $t_restriction->set('element_id', $vn_element_id); $this->_processSettings($t_restriction, $vo_restriction->settings); if ($t_restriction->getPrimaryKey()) { $t_restriction->update(); } else { $t_restriction->insert(); } if ($t_restriction->numErrors()) { $this->addError("There was an error while inserting type restriction {$vs_restriction_code} for metadata element {$vs_element_code}: " . join("; ", $t_restriction->getErrors())); } } } } return true; }
public function getElementsAsDOM() { $t_list = new ca_lists(); $vo_elements = $this->opo_dom->createElement("elementSets"); $qr_elements = $this->opo_db->query("SELECT * FROM ca_metadata_elements WHERE parent_id IS NULL ORDER BY element_id"); $t_element = new ca_metadata_elements(); while ($qr_elements->nextRow()) { $vo_element = $this->opo_dom->createElement("metadataElement"); $vo_element->setAttribute("code", $this->makeIDNO($qr_elements->get("element_code"))); $vo_element->setAttribute("datatype", ca_metadata_elements::getAttributeNameForTypeCode($qr_elements->get("datatype"))); if ($qr_elements->get("list_id")) { $t_list->load($qr_elements->get("list_id")); $vo_element->setAttribute("list", $t_list->get("list_code")); } $vo_labels = $this->opo_dom->createElement("labels"); $qr_element_labels = $this->opo_db->query("SELECT * FROM ca_metadata_element_labels WHERE element_id=?", $qr_elements->get("element_id")); while ($qr_element_labels->nextRow()) { $vo_label = $this->opo_dom->createElement("label"); $vo_label->setAttribute("locale", $this->opt_locale->localeIDToCode($qr_element_labels->get("locale_id"))); $vo_label->appendChild($this->opo_dom->createElement("name", caEscapeForXML($qr_element_labels->get("name")))); if (strlen(trim($qr_element_labels->get("description"))) > 0) { $vo_label->appendChild($this->opo_dom->createElement("description", caEscapeForXML($qr_element_labels->get("description")))); } $vo_labels->appendChild($vo_label); } $vo_element->appendChild($vo_labels); $t_element->load($qr_elements->get("element_id")); $va_settings = $t_element->getSettings(); $va_available_settings = $t_element->getAvailableSettings(); if (is_array($va_settings)) { $vo_settings = $this->opo_dom->createElement("settings"); $vb_append_settings_element = false; foreach ($t_element->getSettings() as $vs_setting => $vs_value) { if ($t_element->isValidSetting($vs_setting) && $vs_value != $va_available_settings[$vs_setting]["default"]) { $vo_setting = $this->opo_dom->createElement("setting", $vs_value); $vo_setting->setAttribute("name", $vs_setting); $vo_settings->appendChild($vo_setting); $vb_append_settings_element = true; } } if ($vb_append_settings_element) { $vo_element->appendChild($vo_settings); } } $vo_sub_elements = $this->getElementAsDOM($qr_elements->get("element_id")); if ($vo_sub_elements) { $vo_element->appendChild($vo_sub_elements); } $vo_restrictions = $this->opo_dom->createElement("typeRestrictions"); foreach ($t_element->getTypeRestrictions() as $va_restriction) { /** @var ca_metadata_type_restrictions $t_restriction */ $t_restriction = new ca_metadata_type_restrictions($va_restriction["restriction_id"]); $vs_table_name = $this->opo_dm->getTableName($t_restriction->get("table_num")); if (!(strlen($vs_table_name) > 0)) { continue; } // there could be lingering restrictions for tables that have since been removed. don't export those. $vo_restriction = $this->opo_dom->createElement("restriction"); $vo_table = $this->opo_dom->createElement("table", $vs_table_name); $vo_restriction->appendChild($vo_table); if ($t_restriction->get("type_id")) { /** @var BaseRelationshipModel $t_instance */ $t_instance = $this->opo_dm->getInstanceByTableNum($t_restriction->get("table_num")); $vs_type_code = $t_instance->getTypeListCode(); $va_item = $t_list->getItemFromListByItemID($vs_type_code, $t_restriction->get("type_id")); $vo_type = $this->opo_dom->createElement("type", $va_item["idno"]); $vo_restriction->appendChild($vo_type); } if (isset($va_restriction['include_subtypes']) && (bool) $va_restriction['include_subtypes']) { $vo_include_subtypes = $this->opo_dom->createElement('includeSubtypes', '1'); $vo_restriction->appendChild($vo_include_subtypes); } if (is_array($va_restriction_settings = $t_restriction->getSettings())) { $vo_settings = $this->opo_dom->createElement("settings"); foreach ($va_restriction_settings as $vs_setting => $vs_value) { $vo_setting = $this->opo_dom->createElement("setting", $vs_value); $vo_setting->setAttribute("name", $vs_setting); $vo_settings->appendChild($vo_setting); } $vo_restriction->appendChild($vo_settings); } $vo_restrictions->appendChild($vo_restriction); } $vo_element->appendChild($vo_restrictions); $vo_elements->appendChild($vo_element); } return $vo_elements; }
public function Save($pa_values = null) { $t_element = $this->getElementObject(false); $t_element->setMode(ACCESS_WRITE); $va_request = $_REQUEST; /* we don't want to modify $_REQUEST since this may cause ugly side-effects */ foreach ($t_element->getFormFields() as $vs_f => $va_field_info) { $t_element->set($vs_f, $_REQUEST[$vs_f]); unset($va_request[$vs_f]); if ($t_element->numErrors()) { foreach ($t_element->errors() as $o_e) { $this->request->addActionError($o_e, 'general'); $this->notification->addNotification($o_e->getErrorDescription(), __NOTIFICATION_TYPE_ERROR__); } } } if ($vn_parent_id = $this->request->getParameter('parent_id', pInteger)) { $t_element->set('parent_id', $vn_parent_id); } if (!$t_element->getPrimaryKey()) { $vb_new = true; $vo_db = $t_element->getDb(); if ($vn_parent_id) { $qr_tmp = $vo_db->query("\n\t\t\t\t\tSELECT MAX(rank) AS rank\n\t\t\t\t\tFROM ca_metadata_elements\n\t\t\t\t\tWHERE parent_id=?\n\t\t\t\t", $vn_parent_id); if (!$qr_tmp->nextRow()) { $t_element->set('rank', 1); } else { $t_element->set('rank', intval($qr_tmp->get('rank')) + 1); } } $t_element->insert(); $vs_message = _t("Added metadata element"); $this->request->setParameter('element_id', $t_element->getPrimaryKey()); } else { $t_element->update(); $vb_new = false; $vs_message = _t("Saved changes to metadata element"); } if ($t_element->numErrors()) { foreach ($t_element->errors() as $o_e) { $this->request->addActionError($o_e, 'general'); $this->notification->addNotification($o_e->getErrorDescription(), __NOTIFICATION_TYPE_ERROR__); } } else { $this->notification->addNotification($vs_message, __NOTIFICATION_TYPE_INFO__); } if ($t_element->getPrimaryKey()) { $va_new_labels = array(); $va_old_labels = array(); $va_delete_labels = array(); foreach ($va_request as $vs_key => $vs_val) { if (!(strpos($vs_key, 'element_labels_Pref') === false)) { /* label field */ $va_matches = array(); if (!(strpos($vs_key, '_new') === false)) { /* new label field */ preg_match('/element_labels_Pref(.*)_new_([0-9]+)/', $vs_key, $va_matches); $va_new_labels[$va_matches[2]][$va_matches[1]] = $vs_val; } else { if (!(strpos($vs_key, '_delete') === false)) { /* delete label */ preg_match('/element_labels_PrefLabel_([0-9]+)_delete/', $vs_key, $va_matches); $va_delete_labels[] = $va_matches[1]; } else { /* existing label field */ preg_match('/element_labels_Pref(.*)_([0-9]+)/', $vs_key, $va_matches); $va_old_labels[$va_matches[2]][$va_matches[1]] = $vs_val; } } unset($va_request[$vs_key]); } } /* insert new labels */ $t_element_label = new ca_metadata_element_labels(); foreach ($va_new_labels as $va_label) { $t_element_label->clear(); foreach ($va_label as $vs_f => $vs_val) { $t_element_label->set($vs_f, $vs_val); } $t_element_label->set('element_id', $t_element->getPrimaryKey()); $t_element_label->setMode(ACCESS_WRITE); $t_element_label->insert(); if ($t_element_label->numErrors()) { foreach ($t_element_label->errors() as $o_e) { $this->request->addActionError($o_e, 'general'); $this->notification->addNotification($o_e->getErrorDescription(), __NOTIFICATION_TYPE_ERROR__); } } } /* delete labels */ foreach ($va_delete_labels as $vn_label) { $t_element_label->load($vn_label); $t_element_label->setMode(ACCESS_WRITE); $t_element_label->delete(false); } /* process old labels */ foreach ($va_old_labels as $vn_key => $va_label) { $t_element_label->load($vn_key); foreach ($va_label as $vs_f => $vs_val) { $t_element_label->set($vs_f, $vs_val); } $t_element_label->set('element_id', $t_element->getPrimaryKey()); $t_element_label->setMode(ACCESS_WRITE); if ($vb_new) { $t_element_label->insert(); } else { $t_element_label->update(); } if ($t_element_label->numErrors()) { foreach ($t_element_label->errors() as $o_e) { $this->request->addActionError($o_e, 'general'); $this->notification->addNotification($o_e->getErrorDescription(), __NOTIFICATION_TYPE_ERROR__); } } } /* process settings */ if (is_array($va_settings = $t_element->getAvailableSettings())) { $vb_need_to_update = false; foreach ($va_settings as $vs_setting_key => $va_setting_info) { if (isset($va_setting_info['refreshOnChange']) && (bool) $va_setting_info['refreshOnChange']) { $t_element->setSetting($vs_setting_key, $va_request['setting_' . $vs_setting_key]); $vb_need_to_update = true; } } if ($vb_need_to_update) { $t_element->update(); $va_settings = $t_element->getAvailableSettings(); } // we need to unset the form timestamp to disable the 'Changes have been made since you loaded this data' warning // when we update() below. the warning makes sense because an update() is called before we get here, but if there // was an actual concurrent save problem , that very update above would have triggered the warning already $vn_timestamp = $_REQUEST['form_timestamp']; unset($_REQUEST['form_timestamp']); foreach ($va_settings as $vs_setting_key => $va_setting_info) { if (isset($va_request['setting_' . $vs_setting_key . '[]'])) { $vs_val = $va_request['setting_' . $vs_setting_key . '[]']; } else { $vs_val = $va_request['setting_' . $vs_setting_key]; } $vs_error = null; if (!$t_element->setSetting($vs_setting_key, $vs_val, $vs_error)) { $this->notification->addNotification(_t("Setting %2 is not valid: %1", $vs_error, $vs_setting_key), __NOTIFICATION_TYPE_ERROR__); continue; } $t_element->update(); } $_REQUEST['form_timestamp'] = $vn_timestamp; } /* process type restrictions */ $t_restriction = new ca_metadata_type_restrictions(null, true); $va_settings = array_keys($t_restriction->getAvailableSettings()); foreach ($_REQUEST as $vs_key => $vs_value) { if (preg_match('!^type_restrictions_table_num_([\\d]+)$!', $vs_key, $va_matches)) { // got one to update if ($t_restriction->load($va_matches[1])) { $t_restriction->setMode(ACCESS_WRITE); $t_restriction->set('table_num', $this->request->getParameter('type_restrictions_table_num_' . $va_matches[1], pInteger)); $t_restriction->set('type_id', ($vn_type_id = $this->request->getParameter('type_restrictions_type_id_' . $va_matches[1], pInteger)) ? $vn_type_id : null); $t_restriction->set('include_subtypes', ($vn_include_subtypes = $this->request->getParameter('type_restrictions_include_subtypes_' . $va_matches[1], pInteger)) ? $vn_include_subtypes : null); foreach ($va_settings as $vs_setting) { $t_restriction->setSetting($vs_setting, $this->request->getParameter('type_restrictions_setting_' . $vs_setting . '_' . $va_matches[1], pString)); } $t_restriction->update(); } continue; } if (preg_match('!^type_restrictions_table_num_new_([\\d]+)$!', $vs_key, $va_matches)) { // got one to create $t_restriction->setMode(ACCESS_WRITE); $t_restriction->set('element_id', $t_element->getPrimaryKey()); $t_restriction->set('table_num', $this->request->getParameter('type_restrictions_table_num_new_' . $va_matches[1], pInteger)); $t_restriction->set('type_id', ($vn_type_id = $this->request->getParameter('type_restrictions_type_id_new_' . $va_matches[1], pInteger)) ? $vn_type_id : null); $t_restriction->set('include_subtypes', ($vn_include_subtypes = $this->request->getParameter('type_restrictions_include_subtypes_new_' . $va_matches[1], pInteger)) ? $vn_include_subtypes : null); foreach ($va_settings as $vs_setting) { $t_restriction->setSetting($vs_setting, $this->request->getParameter('type_restrictions_setting_' . $vs_setting . '_new_' . $va_matches[1], pString)); } $t_restriction->insert(); continue; } if (preg_match('!^type_restrictions_([\\d]+)_delete$!', $vs_key, $va_matches)) { // got one to delete if ($t_restriction->load($va_matches[1])) { $t_restriction->setMode(ACCESS_WRITE); $t_restriction->delete(); } continue; } } CompositeCache::delete($t_element->getPrimaryKey(), 'ElementSets'); CompositeCache::delete($t_element->getPrimaryKey(), 'ElementSetIds'); } $this->Edit(); return; }
/** * Returns an instance of ca_metadata_type_restrictions containing the row (and settings) for the * specified element_set (identified by $pn_element_id) as it relates to the current row; returns * null if element_id is not applicable to the current row */ public function getTypeRestrictionInstance($pn_element_id) { $t_restriction = new ca_metadata_type_restrictions(); if (is_subclass_of($this, 'BaseRelationshipModel') && $t_restriction->load(array('element_id' => (int) $pn_element_id, 'table_num' => (int) $this->tableNum(), 'type_id' => $this->get('type_id')))) { return $t_restriction; } elseif ($t_restriction->load(array('element_id' => (int) $pn_element_id, 'table_num' => (int) $this->tableNum(), 'type_id' => $this->get($this->ATTRIBUTE_TYPE_ID_FLD)))) { return $t_restriction; } elseif ($t_restriction->load(array('element_id' => (int) $pn_element_id, 'table_num' => (int) $this->tableNum(), 'type_id' => null))) { return $t_restriction; } // try going up the hierarchy to find one that we can inherit from if ($t_type_instance = $this->getTypeInstance()) { $va_ancestors = $t_type_instance->getHierarchyAncestors(null, array('idsOnly' => true)); if (is_array($va_ancestors)) { array_pop($va_ancestors); // get rid of root if (sizeof($va_ancestors)) { $qr_res = $this->getDb()->query("\n\t\t\t\t\t\t\tSELECT restriction_id\n\t\t\t\t\t\t\tFROM ca_metadata_type_restrictions\n\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\ttype_id IN (?) AND table_num = ? AND include_subtypes = 1 AND element_id = ?\n\t\t\t\t\t\t", array($va_ancestors, (int) $this->tableNum(), (int) $pn_element_id)); if ($qr_res->nextRow()) { if ($t_restriction->load($qr_res->get('restriction_id'))) { return $t_restriction; } } } } } return null; }
/** * Load type restriction for specified table and type and return loaded model instance. * Will return specific restriction for type_id, or a general (type_id=null) restriction if no * type-specific restriction is defined. * * @param $pn_table_num - table_num of type restriction * @param $pn_type_id - type_id of type restriction; leave null if you want a non-type-specific restriction * @return ca_metadata_type_restrictions instance - will be loaded with type restriction */ public function getTypeRestrictionInstanceForElement($pn_table_num, $pn_type_id) { if (!($vn_element_id = $this->getPrimaryKey())) { return null; } // element must be loaded if ($this->get('parent_id')) { return null; } // element must be root of hierarchy $t_restriction = new ca_metadata_type_restrictions(); if ($pn_type_id > 0 && $t_restriction->load(array('table_num' => (int) $pn_table_num, 'type_id' => (int) $pn_type_id, 'element_id' => (int) $vn_element_id))) { return $t_restriction; } else { if ($t_restriction->load(array('table_num' => (int) $pn_table_num, 'type_id' => null, 'element_id' => (int) $vn_element_id))) { return $t_restriction; } // try going up the hierarchy to find one that we can inherit from if ($pn_type_id && ($t_type_instance = new ca_list_items($pn_type_id))) { $va_ancestors = $t_type_instance->getHierarchyAncestors(null, array('idsOnly' => true)); if (is_array($va_ancestors)) { array_pop($va_ancestors); // get rid of root if (sizeof($va_ancestors)) { $qr_res = $this->getDb()->query("\n\t\t\t\t\t\t\tSELECT restriction_id\n\t\t\t\t\t\t\tFROM ca_metadata_type_restrictions\n\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\ttype_id IN (?) AND table_num = ? AND include_subtypes = 1 AND element_id = ?\n\t\t\t\t\t\t", array($va_ancestors, (int) $pn_table_num, (int) $vn_element_id)); if ($qr_res->nextRow()) { if ($t_restriction->load($qr_res->get('restriction_id'))) { return $t_restriction; } } } } } } return null; }
/** * */ public function __construct($pn_id = null, $pb_filter_tables = false) { global $_ca_metadata_type_restriction_settings; parent::__construct($pn_id); # call superclass constructor // $this->SETTINGS = new ModelSettings($this, 'settings', $_ca_metadata_type_restriction_settings); if (!ca_metadata_type_restrictions::$s_loaded_relationship_tables) { require_once __CA_MODELS_DIR__ . '/ca_relationship_types.php'; $t_rel = new ca_relationship_types(); $va_rels = $t_rel->getRelationshipsUsingTypes(); $o_dm = Datamodel::load(); foreach ($va_rels as $vn_table_num => $va_rel_table_info) { BaseModel::$s_ca_models_definitions['ca_metadata_type_restrictions']['FIELDS']['table_num']['BOUNDS_CHOICE_LIST'][$va_rel_table_info['name']] = $vn_table_num; } if ($pb_filter_tables) { BaseModel::$s_ca_models_definitions['ca_metadata_type_restrictions']['FIELDS']['table_num']['BOUNDS_CHOICE_LIST'] = caFilterTableList(BaseModel::$s_ca_models_definitions['ca_metadata_type_restrictions']['FIELDS']['table_num']['BOUNDS_CHOICE_LIST'], array('sort' => true)); } ca_metadata_type_restrictions::$s_loaded_relationship_tables = true; } }