From 918c2bfc344c39b2552982255263e12f17a3d273 Mon Sep 17 00:00:00 2001 From: SteveD Date: Fri, 21 Dec 2012 22:33:02 +0000 Subject: [PATCH] Restructure use of predefined lists in extended user classes - get rid of global, more general interface which can be used with a DB or similar as well. --- e107_admin/sql/extended_timezones.php | 210 +-- e107_handlers/user_extended_class.php | 1808 ++++++++++++------------- 2 files changed, 1036 insertions(+), 982 deletions(-) diff --git a/e107_admin/sql/extended_timezones.php b/e107_admin/sql/extended_timezones.php index 822b60cc4..24955ade9 100644 --- a/e107_admin/sql/extended_timezones.php +++ b/e107_admin/sql/extended_timezones.php @@ -1,78 +1,134 @@ - text pair -The text is displayed in a drop-down; the value is returned. -If function timezones_value() exists, it is called to create the displayed text -*/ - -//FIXME - remove globals. -global $timezones_list; -if (!is_array($timezones_list)) -{ -$timezones_list = array( - array('-12', "International DateLine West"), - array('-11', "Samoa"), - array('-10', "Hawaii"), - array( '-9', "Alaska"), - array( '-8', "Pacific Time (US and Canada)"), - array( '-7', "Mountain Time (US and Canada)"), - array( '-6', "Central Time (US and Canada), Central America"), - array( '-5', "Eastern Time (US and Canada)"), - array( '-4', "Atlantic Time (Canada)"), - array( '-3.30', 'Newfoundland'), - array( '-3', "Greenland, Brasilia, Buenos Aires, Georgetown"), - array( '-2', "Mid-Atlantic"), - array( '-1', "Azores, Cape Verde Islands"), - array( '+0', "UK, Ireland, Lisbon"), - array( '+1', "West Central Africa, Western Europe"), - array( '+2', "Greece, Egypt, parts of Africa"), - array( '+3', "Russia, Baghdad, Kuwait, Nairobi"), - array( '+3.30', 'Tehran, Iran'), - array( '+4', "Abu Dhabi, Kabul"), - array( '+4.30', 'Afghanistan'), - array( '+5', "Islamabad, Karachi"), - array( '+5.30', "Mumbai, Delhi, Calcutta"), - array( '+5.45', 'Kathmandu'), - array( '+6', "Astana, Dhaka"), - array( '+7', "Bangkok, Rangoon"), - array( '+8', "Hong Kong, Singapore, Perth, Beijing"), - array( '+9', "Tokyo, Seoul"), - array( '+9.30', 'Darwin, Adelaide'), - array('+10', "Brisbane, Canberra, Sydney, Melbourne"), - array('+10.30', 'Lord Howe Island'), - array('+11', "Soloman Islands"), - array('+11.30', 'Norfolk Island'), - array('+12', "New Zealand, Fiji, Marshall Islands"), - array('+13', "Tonga, Nuku'alofa, Rawaki Islands"), - array('+13.45', 'Chatham Island'), - array('+14', 'Kiribati: Line Islands') - ); -} - -if (!function_exists('timezones_value')) -{ - function timezones_value($key, $value) - { - return 'GMT'.$key.' - '.$value; - } -} - + text pair +The text is displayed in a drop-down; the value is returned. +If function timezones_value() exists, it is called to create the displayed text +*/ + +class extended_timezones +{ + + private $timezonesList = array( + '-12' => "International DateLine West", + '-11' => "Samoa", + '-10' => "Hawaii", + '-9' => "Alaska", + '-8' => "Pacific Time (US and Canada)", + '-7' => "Mountain Time (US and Canada)", + '-6' => "Central Time (US and Canada), Central America", + '-5' => "Eastern Time (US and Canada)", + '-4' => "Atlantic Time (Canada)", + '-3.30' => 'Newfoundland', + '-3' => "Greenland, Brasilia, Buenos Aires, Georgetown", + '-2' => "Mid-Atlantic", + '-1' => "Azores, Cape Verde Islands", + '+0' => "UK, Ireland, Lisbon", + '+1' => "West Central Africa, Western Europe", + '+2' => "Greece, Egypt, parts of Africa", + '+3' => "Russia, Baghdad, Kuwait, Nairobi", + '+3.30' => 'Tehran, Iran', + '+4' => "Abu Dhabi, Kabul", + '+4.30' => 'Afghanistan', + '+5' => "Islamabad, Karachi", + '+5.30' => "Mumbai, Delhi, Calcutta", + '+5.45' => 'Kathmandu', + '+6' => "Astana, Dhaka", + '+7' => "Bangkok, Rangoon", + '+8' => "Hong Kong, Singapore, Perth, Beijing", + '+9' => "Tokyo, Seoul", + '+9.30' => 'Darwin, Adelaide', + '+10' => "Brisbane, Canberra, Sydney, Melbourne", + '+10.30' => 'Lord Howe Island', + '+11' => "Soloman Islands", + '+11.30' => 'Norfolk Island', + '+12' => "New Zealand, Fiji, Marshall Islands", + '+13' => "Tonga, Nuku'alofa, Rawaki Islands", + '+13.45' => 'Chatham Island', + '+14' => 'Kiribati: Line Islands' + ); + + + private $isEOF = FALSE; // True if at last element of list + private $bufferValid = FALSE; + + + /** + * Call before using the 'next' format option, to ensure the array is indexed from the beginning + */ + public function pointerReset() + { + $this->isEOF = (FALSE === reset($this->timezonesList)); + $this->bufferValid = TRUE; + } + + + /** + * Return a formatted timezone value + * + * @param mixed $key - the key value to select + * @param string $formatSpec - defines format of return value + * + * @return mixed (according to $formatSpec). FALSE if no value available + * 'array' - a single-element array; key as passed, and value to match key + * 'next' - as 'array', but ignores the passed $key and moves to next value. + * default - a string usable for display + */ + public function getValue($key, $formatSpec = '') + { + if ($formatSpec == 'next') + { + if (!$this->bufferValid) $this->pointerReset; // Make sure buffer is defined + if ($this->isEOF) return FALSE; + $key = key($this->timezonesList); + $val = current($this->timezonesList); + if (FALSE === $val) + { + $this->isEOF = TRUE; + return FALSE; + } + $this->isEOF = (FALSE === next($this->timezonesList)); + return array($key => $val); + } + + $exists = isset($this->timezonesList[$key]); + if (!$exists) return FALSE; + + $val = $this->timezonesList[$key]; + if ($formatSpec == 'array') + { + return array($key => $val); + } + + // Default (as per earlier implementations) - can be specified with 'display' format + return 'GMT'.$key.' - '.$val; + } +} + + ?> \ No newline at end of file diff --git a/e107_handlers/user_extended_class.php b/e107_handlers/user_extended_class.php index 964a8597a..472029e62 100644 --- a/e107_handlers/user_extended_class.php +++ b/e107_handlers/user_extended_class.php @@ -1,906 +1,904 @@ -typeArray = array( - 'text' => 1, - 'radio' => 2, - 'dropdown' => 3, - 'db field' => 4, - 'textarea' => 5, - 'integer' => 6, - 'date' => 7, - 'language' => 8, - 'list' => 9, - 'checkbox' => 10, - 'predefined' => 11, // DON'T USE IT IN PREDEFINED FIELD XML!!! Used in plugin installation routine. - ); - - $this->user_extended_types = array( - 1 => UE_LAN_1, - 2 => UE_LAN_2, - 3 => UE_LAN_3, - 4 => UE_LAN_4, - 5 => UE_LAN_5, - 6 => UE_LAN_6, - 7 => UE_LAN_7, - 8 => UE_LAN_8, - 9 => UE_LAN_9, - 10=> UE_LAN_10 - ); - - //load array with field names from main user table, so we can disallow these - // user_new, user_timezone deleted for 0.8 - $this->reserved_names = array ( - 'id', 'name', 'loginname', 'customtitle', 'password', - 'sess', 'email', 'signature', 'image', 'hideemail', - 'join', 'lastvisit', 'currentvisit', 'chats', - 'comments', 'forums', 'ip', 'ban', 'prefs', 'viewed', - 'visits', 'admin', 'login', 'class', 'baseclasslist', 'perms', 'pwchange', - 'xup' - ); - - $sql = e107::getDB(); - - // Read in all the field and category fields - // At present we load all fields into common array - may want to split system and non-system - $this ->catDefinitions = array(); // Categories array - $this->fieldDefinitions = array(); // Field definitions array - $this->nameIndex = array(); // Index of names => field IDs - $this->systemCount = 0; - $this->userCount = 0; - - if($sql->db_Select('user_extended_struct', '*', "user_extended_struct_text != '_system_' ORDER BY user_extended_struct_order ASC")) - { - while($row = $sql->db_Fetch(MYSQL_ASSOC)) - { - if ($row['user_extended_struct_type'] == 0) - { // Its a category - $this->catDefinitions[$row['user_extended_struct_id']] = $row; - } - else - { // Its a field definition - $this->fieldDefinitions[$row['user_extended_struct_id']] = $row; - $this->nameIndex['user_'.$row['user_extended_struct_name']] = $row['user_extended_struct_id']; // Create name to ID index - if ($row['user_extended_struct_text'] == '_system_') - { - $this->systemCount++; - } - else - { - $this->userCount++; - } - } - } - } - } - - - - /** - * Check for reserved field names. - * (Names which clash with the 'normal' user table aren't allowed) - * - * @param string $name - name of field bweing checked (no 'user_' prefix) - * - * @return boolean TRUE if disallowed name - */ - public function user_extended_reserved($name) - { - return (in_array($name, $this->reserved_names)); - } - - - - // Adds the _FIELD_TYPES array to the data, ready for saving in the DB. - function addFieldTypes(&$target) - { - $target['_FIELD_TYPES'] = array(); // We should always want to recreate the array, even if it exists - foreach ($target['data'] as $k => $v) - { - if (isset($this->nameIndex[$k])) - { - switch ($this->fieldDefinitions[$this->nameIndex[$k]]['user_extended_struct_type']) - { - case EUF_TEXT : - case EUF_DB_FIELD : - case EUF_TEXTAREA : - case EUF_DROPDOWN : - case EUF_DATE : - case EUF_LANGUAGE : - case EUF_PREDEFINED : - case EUF_CHECKBOX : - case EUF_RADIO : - $target['_FIELD_TYPES'][$k] = 'todb'; - break; - - case EUF_INTEGER : - $target['_FIELD_TYPES'][$k] = 'int'; - break; - } - } - } - } - - - - /** - * For all UEFs not in the target array, adds the default value - * Also updates the _FIELD_TYPES array, so call this last thing before writing to the DB - * - * @param $target - pointer to data array - */ - public function addDefaultFields(&$target) - { - //$target['_FIELD_TYPES'] = array(); // We should always want to recreate the array, even if it exists - foreach ($this->fieldDefinitions as $k => $defs) - { - $f = 'user_'.$defs['user_extended_struct_name']; - if (!isset($target['data'][$f]) && $this->fieldDefinitions[$k]['user_extended_struct_default']) - { - switch ($this->fieldDefinitions[$k]['user_extended_struct_type']) - { - case EUF_TEXT : - case EUF_DB_FIELD : - case EUF_TEXTAREA : - case EUF_DROPDOWN : - case EUF_DATE : - case EUF_LANGUAGE : - case EUF_PREDEFINED : - - $target['data'][$f] = $this->fieldDefinitions[$k]['user_extended_struct_default']; - $target['_FIELD_TYPES'][$f] = 'todb'; - break; - case EUF_RADIO : - case EUF_INTEGER : - $target['data'][$f] = $this->fieldDefinitions[$k]['user_extended_struct_default']; - $target['_FIELD_TYPES'][$f] = 'int'; - break; - case EUF_CHECKBOX : - $target['data'][$f] = $this->fieldDefinitions[$k]['user_extended_struct_default']; - $target['_FIELD_TYPES'][$f] = 'array'; - break; - } - } - } - } - - - - // Validate a single extended user field - // $val is whatever the user entered. - // $params is the field definition - // Return FALSE if acceptable, TRUE if fail , error message on regex fail if the message is defined - function user_extended_validate_entry($val, $params) - { - global $tp; - $parms = explode('^,^', $params['user_extended_struct_parms']); - $requiredField = $params['user_extended_struct_required'] == 1; - $regex = $tp->toText($parms[1]); - $regexfail = $tp->toText($parms[2]); - if (defined($regexfail)) { $regexfail = constant($regexfail); } - if($val == '' && $requiredField) return TRUE; - switch ($type) - { - case EUF_DATE : - if ($requiredField && ($val == '0000-00-00')) return TRUE; - break; - } - if($regex != "" && $val != "") - { - if(!preg_match($regex, $val)) return $regexfail ? $regexfail : TRUE; - } - return FALSE; // Pass by default here - } - - - - /** - * Validate all user-modifable extended user fields which are presented. - * Primarily intended to validate data entered by a user or admin - * - * @param array $inArray is the input data (usually from $_POST or $_POST['ue'], although doesn't have to be) - may have 'surplus' values - * @param array $hideArray is a set of possible 'hide' flags - * @param boolean $isSignup TRUE causes required fields to be specifically checked, else only data passed is checked - * - * @return array with three potential subkeys: - * 'data' - valid data values (key is field name) - * ['data']['user_hidden_fields'] is the hidden fields - * 'errors' - data values in error - * 'errortext' - error message corresponding to erroneous value - * - * @todo - does $hidden_fields need to be merged with values for fields not processed? (Probably not - should only relate to fields current user can see) - * @todo - make sure admin can edit fields of other users - */ - public function userExtendedValidateAll($inArray, $hideArray, $isSignup=FALSE) - { - global $tp; - $eufVals = array(); // 'Answer' array - $hideFlags = array(); - - foreach ($this->fieldDefinitions as $k => $defs) - { - $category = $defs['user_extended_struct_parent']; - if (($category == 0) || ($isSignup && (int) $this->catDefinitions[$category]['user_extended_struct_applicable'] === (int) e_UC_MEMBER && (int) $this->catDefinitions[$category]['user_extended_struct_write'] === (int) e_UC_MEMBER) || (check_class($this->catDefinitions[$category]['user_extended_struct_applicable']) && check_class($this->catDefinitions[$category]['user_extended_struct_write']))) - { // Category applicable to user - - if (($isSignup && (int) $defs['user_extended_struct_applicable'] === (int) e_UC_MEMBER && (int) $defs['user_extended_struct_write'] === (int) e_UC_MEMBER) || (check_class($defs['user_extended_struct_applicable']) && check_class($defs['user_extended_struct_write']))) - { // User can also update field - $f = 'user_'.$defs['user_extended_struct_name']; - if (isset($inArray[$f]) || ($isSignup && ($defs['user_extended_struct_required'] == 1))) - { // Only allow valid keys - $val = varset($inArray[$f], FALSE); - $err = $this->user_extended_validate_entry($val, $defs); - if ($err === true) - { // General error - usually empty field; could be unacceptable value, or regex fail and no error message defined - $eufVals['errortext'][$f] = str_replace('--SOMETHING--',$tp->toHtml(defset($defs['user_extended_struct_text'], $defs['user_extended_struct_text']),FALSE,'defs'),LAN_USER_75); - $eufVals['errors'][$f] = ERR_GENERIC; - } - elseif ($err) - { // Specific error message returned - usually regex fail - $eufVals['errortext'][$f] = $err; - $eufVals['errors'][$f] = ERR_GENERIC; - } - elseif (!$err) - { - $eufVals['data'][$f] = $tp->toDB($val); - } - if (isset($hideArray[$f])) - { - $hideFlags[] = $f; - } - } - } - } - } - $hidden_fields = implode('^', $hideFlags); - if ($hidden_fields != '') - { - $hidden_fields = '^'.$hidden_fields.'^'; - } - $eufVals['data']['user_hidden_fields'] = $hidden_fields; - - return $eufVals; - } - - - - - function user_extended_get_categories($byID = TRUE) - { - $ret = array(); - global $sql; - if($sql->db_Select("user_extended_struct", "*", "user_extended_struct_type = 0 ORDER BY user_extended_struct_order ASC")) - { - if($byID == TRUE) - { - while($row = $sql->db_Fetch()) - { - $ret[$row['user_extended_struct_id']][] = $row; - } - } - else - { - $ret = $sql->db_getList(); - } - } - return $ret; - } - - - // Get the definition of all fields, or those in a specific category, grouped by category ID - // Reads non-system fields only - function user_extended_get_fields($cat = "") - { - global $sql; - $ret = array(); - $more = ($cat) ? " AND user_extended_struct_parent = ".intval($cat)." " : ""; - if($sql->db_Select("user_extended_struct", "*", "user_extended_struct_type > 0 AND user_extended_struct_text != '_system_' {$more} ORDER BY user_extended_struct_order ASC")) - { - while($row = $sql->db_Fetch(MYSQL_ASSOC)) - { - $ret[$row['user_extended_struct_parent']][] = $row; - } - } - return $ret; - } - - // Get the definition of all fields, or those in a specific category, indexed by field ID (or some other field by specifying $indexField) - function user_extended_get_fieldList($cat = "", $indexField = 'user_extended_struct_id') - { - global $sql; - $more = ($cat != '') ? " AND user_extended_struct_parent = ".intval($cat)." " : ""; - if($sql->db_Select("user_extended_struct", "*", "user_extended_struct_type > 0 AND user_extended_struct_text != '_system_' {$more} ORDER BY user_extended_struct_order ASC")) - { - while($row = $sql->db_Fetch(MYSQL_ASSOC)) - { - $ret[$row[$indexField]] = $row; - } - } - return $ret; - } - - - // Return the field creation text for a definition - function user_extended_type_text($type, $default) - { - global $tp; - if(!is_numeric($type)) - { - return false; - } - - switch ($type) - { - case EUF_INTEGER : - $db_type = 'INT(11)'; - break; - - case EUF_DATE : - $db_type = 'DATE NOT NULL'; - break; - - case EUF_TEXTAREA: - $db_type = 'TEXT'; - break; - - case EUF_TEXT : - case EUF_RADIO : - case EUF_DROPDOWN : - case EUF_DB_FIELD : - case EUF_LANGUAGE : - case EUF_PREDEFINED : - case EUF_CHECKBOX : - $db_type = 'VARCHAR(255)'; - break; - - case EUF_CATEGORY: - return ''; - break; - - default: - e107::getMessage()->addDebug("Unknown type '{$type}' for user extended field."); - return false; - break; - - } - if($type != EUF_DB_FIELD && $type != EUF_TEXTAREA && $default != '') - { - $default_text = " DEFAULT '".$tp -> toDB($default, true)."'"; - } - else - { - $default_text = ''; - } - return $db_type.$default_text; - } - - - function user_extended_field_exist($name) - { - global $sql, $tp; - return $sql->db_Count('user_extended_struct','(*)', "WHERE user_extended_struct_name = '".$tp -> toDB($name, true)."'"); - } - - function clear_cache() - { - $e107 = e107::getInstance(); - $e107->ecache->clear_sys('nomd5_extended_struct'); - } - - // For use by plugins to add extended user fields and won't be visible anywhere else - function user_extended_add_system($name, $type, $default = '', $source = '_system_') - { - return $this->user_extended_add($name, '_system_', $type, $source, '', $default, 0, 255, 255, 255, 0, 0); - } - - - function user_extended_add($name, $text, $type, $parms, $values, $default, $required, $read, $write, $applicable, $order='', $parent) - { - global $sql, $tp; - $this->clear_cache(); - if(is_array($name)) - { - extract($name); - } - if(!is_numeric($type)) - { - $type = $this->typeArray[$type]; - } - - if (!$this->user_extended_field_exist($name) && !$this->user_extended_reserved($name)) - { - $field_info = $this->user_extended_type_text($type, $default); - - // wrong type - if(false === $field_info) return false; - - if($order === '' && $field_info) - { - if($sql->db_Select('user_extended_struct','MAX(user_extended_struct_order) as maxorder','1')) - { - $row = $sql->db_Fetch(); - if(is_numeric($row['maxorder'])) - { - $order = $row['maxorder']+1; - } - } - } - // field of type category - if($field_info) - { - $sql->db_Select_gen('ALTER TABLE #user_extended ADD user_'.$tp -> toDB($name, true).' '.$field_info); - } - - $sql->db_Insert('user_extended_struct',"null,'".$tp -> toDB($name, true)."','".$tp -> toDB($text, true)."','".intval($type)."','".$tp -> toDB($parms, true)."','".$tp -> toDB($values, true)."', '".$tp -> toDB($default, true)."', '".intval($read)."', '".intval($write)."', '".intval($required)."', '0', '".intval($applicable)."', '".intval($order)."', '".intval($parent)."'"); - if ($this->user_extended_field_exist($name)) - { - return TRUE; - } - } - return FALSE; - } - - - - function user_extended_modify($id, $name, $text, $type, $parms, $values, $default, $required, $read, $write, $applicable, $parent) - { - global $sql, $tp; - if ($this->user_extended_field_exist($name)) - { - $field_info = $this->user_extended_type_text($type, $default); - // wrong type - if(false === $field_info) return false; - - // field of type category - if($field_info) - { - $sql->db_Select_gen("ALTER TABLE #user_extended MODIFY user_".$tp -> toDB($name, true)." ".$field_info); - } - - $newfield_info = " - user_extended_struct_text = '".$tp -> toDB($text, true)."', - user_extended_struct_type = '".intval($type)."', - user_extended_struct_parms = '".$tp -> toDB($parms, true)."', - user_extended_struct_values = '".$tp -> toDB($values, true)."', - user_extended_struct_default = '".$tp -> toDB($default, true)."', - user_extended_struct_required = '".intval($required)."', - user_extended_struct_read = '".intval($read)."', - user_extended_struct_write = '".intval($write)."', - user_extended_struct_applicable = '".intval($applicable)."', - user_extended_struct_parent = '".intval($parent)."' - WHERE user_extended_struct_id = '".intval($id)."' - "; - return $sql->db_Update("user_extended_struct", $newfield_info); - } - } - - function user_extended_remove($id, $name) - { - global $sql, $tp; - $this->clear_cache(); - if ($this->user_extended_field_exist($name)) - { - // FIXME - no table structure changes for categories - // but no good way to detect it right now - ignore the sql error for now, fix it asap - $sql->db_Select_gen("ALTER TABLE #user_extended DROP user_".$tp -> toDB($name, true)); - - if(is_numeric($id)) - { - $sql->db_Delete("user_extended_struct", "user_extended_struct_id = '".intval($id)."' "); - } - else - { - $sql->db_Delete("user_extended_struct", "user_extended_struct_name = '".$tp -> toDB($id, true)."' "); - } - return !($this->user_extended_field_exist($name)); - } - } - - function user_extended_hide($struct, $curval) - { - $chk = ($curval) ? " checked='checked' " : ""; - $name = "hide[user_".$struct['user_extended_struct_name']."]"; - return " ".UE_LAN_HIDE; - } - - - - function user_extended_edit($struct, $curval) - { - global $tp; - if(trim($curval) == "" && $struct['user_extended_struct_default'] != "") - { - $curval = $struct['user_extended_struct_default']; - } - $choices = explode(",",$struct['user_extended_struct_values']); - foreach($choices as $k => $v) - { - $choices[$k] = str_replace("[E_COMMA]", ",", $choices[$k]); - } - $parms = explode("^,^",$struct['user_extended_struct_parms']); - $include = preg_replace("/\n/", " ", $tp->toHtml($parms[0])); - $regex = $tp->toText($parms[1]); - $regexfail = $tp->toText($parms[2]); - $fname = "ue[user_".$struct['user_extended_struct_name']."]"; - if(strpos($include, 'class') === FALSE) - { - $include .= " class='tbox' "; - } - - - switch($struct['user_extended_struct_type']) - { - case EUF_TEXT : //textbox - case EUF_INTEGER : //integer - $ret = ""; - return $ret; - break; - - case EUF_RADIO : //radio - $ret = ''; - foreach($choices as $choice) - { - $choice = trim($choice); - $choice = deftrue($choice, $choice); - $chk = ($curval == $choice)? " checked='checked' " : ""; - $ret .= " {$choice}"; - } - return $ret; - break; - - case EUF_CHECKBOX : //checkboxes - foreach($choices as $choice) - { - $choice = trim($choice); - if(strpos($choice,"|")!==FALSE) - { - list($val,$label) = explode("|",$choice); - } - else - { - $val = $choice; - $label = $choice; - } - $label = deftrue($label, $label); - $chk = ($curval == $val)? " checked='checked' " : ""; - $ret .= " {$label}
"; - } - return $ret; - break; - - case EUF_DROPDOWN : //dropdown - $ret = "\n"; - return $ret; - break; - - case EUF_PREDEFINED : // predefined list, shown in dropdown - $filename = e_ADMIN.'sql/extended_'.trim($struct['user_extended_struct_values']).'.php'; - if (!is_readable($filename)) return 'No file: '.$filename; - require($filename); - $list_name = $struct['user_extended_struct_values'].'_list'; - $display_func = $struct['user_extended_struct_values'].'_value'; - if (!function_exists($display_func)) $display_func = ''; - $source_data = $$list_name; - $ret = "\n"; - return $ret; - break; - - case EUF_DB_FIELD : //db_field - global $sql; - $order = ($choices[3]) ? "ORDER BY ".$tp -> toDB($choices[3], true) : ""; - - if($sql->db_Select($tp -> toDB($choices[0], true), $tp -> toDB($choices[1], true).",".$tp -> toDB($choices[2], true), "1 $order")){ - $choiceList = $sql->db_getList('ALL',FALSE); - $ret = "\n"; - return $ret; - } else { - return ""; - } - break; - - case EUF_TEXTAREA : //textarea - return ""; - break; - - case EUF_DATE : //date - return e107::getForm()->datepicker($fname,$curval,'dateformat=yy-mm-dd'); - break; - - case EUF_LANGUAGE : // language - require_once(e_HANDLER."file_class.php"); - $fl = new e_file; - $lanlist = $fl->get_dirs(e_LANGUAGEDIR); - sort($lanlist); - $ret = "\n"; - break; - - } - - return $ret; - } - - function user_extended_getStruct($orderby="user_extended_struct_order") - { - if($ueStruct = getcachedvars('ue_struct')) - { - return $ueStruct; - } - global $tp; - $ret = array(); - $parms = ""; - if($orderby != "") - { - $parms = "1 ORDER BY ".$tp -> toDB($orderby, true); - } - $sql_ue = new db; // Use our own db to avoid interference with other objects - if($sql_ue->db_Select('user_extended_struct','*',$parms)) - { - while($row = $sql_ue->db_Fetch()) - { - $ret['user_'.$row['user_extended_struct_name']] = $row; - } - } - cachevars('ue_struct',$ret); - return $ret; - } - - - function parse_extended_xml($contents, $no_cache = FALSE) - { - if($no_cache == FALSE && $this->extended_xml) - { - return $this->extended_xml; - } - - $xml = e107::getXml(); - $data = $xml->loadXMLfile(e_CORE."xml/user_extended.xml", true); - $ret['version'] = $data['@attributes']['version']; - unset($info); - foreach($data['item'] as $item) - { - if(is_array($item['include_text']) && !count($item['include_text'])) - { - $item['include_text'] = ''; - } - $info = array( - "name" => $item['@attributes']['name'], - "text" => "UE_LAN_".strtoupper($item['@attributes']['name']), - "type" => $item['type'], - "values" => $item['values'], - "default" => $item['default'], - "required" => $item['required'], - "read" => $item['read'], - "write" => $item['write'], - "applicable" => $item['applicable'], - "include_text" => $item['include_text'], - "parms" => $item['include_text'], - "regex" => $item['regex'] - ); - if(is_array($item['default']) && $item['default'] == '') - { - $info['default'] = 0; - } - if($item['regex']) - { - $info['parms'] .= $item['include_text']."^,^".$item['regex']."^,^LAN_UE_FAIL_".strtoupper($item['@attributes']['name']); - } - $ret[$item['@attributes']['name']] = $info; - } - $this->extended_xml = $ret; - return $this->extended_xml; - } - - /** - * Proxy Method to retrieve the value of an extended field - * @param int $uid - * @param var $field_name - * @param object $ifnotset [optional] - * @return mixed - */ - function get($uid, $field_name, $ifnotset=false) - { - return user_extended_getvalue($uid, $field_name, $ifnotset); - } - - - - /** - * Proxy method for setting the value of an extended field - * (inserts or updates) - * - * @param integer $uid - * @param string $field_name eg. location - * @param string $newvalue eg. USA - * @param string $fieldType [optional] default 'todb' | - * @return boolean; - */ - function set($uid, $field_name, $newvalue, $fieldType = 'todb') - { - return $this->user_extended_setvalue($uid, $field_name, $newvalue, $fieldType); - } - - - /** - * Set the value of an extended field - * - * $ue = new e107_user_extended; - * $result = $ue->user_extended_setvalue(1, 'location', 'Pittsburgh'); - * - * - */ - function user_extended_setvalue($uid, $field_name, $newvalue, $fieldType = 'todb') - { - $sql = e107::getDb(); - $tp = e107::getParser(); - - $uid = (int)$uid; - switch($fieldType) - { - case 'int': - $newvalue = (int)$newvalue; - break; - - case 'escape': - $newvalue = "'".mysql_real_escape_string($newvalue)."'"; - break; - - default: - $newvalue = "'".$tp->toDB($newvalue)."'"; - break; - } - if(substr($field_name, 0, 5) != 'user_') - { - $field_name = 'user_'.$field_name; - } - $qry = " - INSERT INTO `#user_extended` (user_extended_id, {$field_name}) - VALUES ({$uid}, {$newvalue}) - ON DUPLICATE KEY UPDATE {$field_name} = {$newvalue} - "; - return $sql->db_Select_gen($qry); - } - - - /** - * Retrieve the value of an extended field - * - * $ue = new e107_user_extended; - * $value = $ue->user_extended_getvalue(2, 'location'); - * - */ - function user_extended_getvalue($uid, $field_name, $ifnotset=false) - { - $uid = intval($uid); - if(substr($field_name, 0, 5) != 'user_') - { - $field_name = 'user_'.$field_name; - } - $uinfo = get_user_data($uid); - if (!isset($uinfo[$field_name])) return $ifnotset; - return $uinfo[$field_name]; - } - - // Given a predefined list field, returns the display text corresponding to the passed value - function user_extended_display_text($table,$value) - { - $filename = e_ADMIN.'sql/extended_'.$table.'.php'; - if (!is_readable($filename)) return 'No file: '.$filename; - require_once($filename); - $list_name = $table.'_list'; - $display_func = $table.'_value'; - if (!function_exists($display_func)) $display_func = ''; - $source_data = $$list_name; - foreach($source_data as $v) - { - if ($value == $v[0]) - { - if ($display_func) return $display_func($v[0],$v[1]); - return $v[1]; - } - } - return '????'; - } - -} +typeArray = array( + 'text' => 1, + 'radio' => 2, + 'dropdown' => 3, + 'db field' => 4, + 'textarea' => 5, + 'integer' => 6, + 'date' => 7, + 'language' => 8, + 'list' => 9, + 'checkbox' => 10, + 'predefined' => 11, // DON'T USE IT IN PREDEFINED FIELD XML!!! Used in plugin installation routine. + ); + + $this->user_extended_types = array( + 1 => UE_LAN_1, + 2 => UE_LAN_2, + 3 => UE_LAN_3, + 4 => UE_LAN_4, + 5 => UE_LAN_5, + 6 => UE_LAN_6, + 7 => UE_LAN_7, + 8 => UE_LAN_8, + 9 => UE_LAN_9, + 10=> UE_LAN_10 + ); + + //load array with field names from main user table, so we can disallow these + // user_new, user_timezone deleted for 0.8 + $this->reserved_names = array ( + 'id', 'name', 'loginname', 'customtitle', 'password', + 'sess', 'email', 'signature', 'image', 'hideemail', + 'join', 'lastvisit', 'currentvisit', 'chats', + 'comments', 'forums', 'ip', 'ban', 'prefs', 'viewed', + 'visits', 'admin', 'login', 'class', 'baseclasslist', 'perms', 'pwchange', + 'xup' + ); + + $sql = e107::getDB(); + + // Read in all the field and category fields + // At present we load all fields into common array - may want to split system and non-system + $this ->catDefinitions = array(); // Categories array + $this->fieldDefinitions = array(); // Field definitions array + $this->nameIndex = array(); // Index of names => field IDs + $this->systemCount = 0; + $this->userCount = 0; + + if($sql->db_Select('user_extended_struct', '*', "user_extended_struct_text != '_system_' ORDER BY user_extended_struct_order ASC")) + { + while($row = $sql->db_Fetch(MYSQL_ASSOC)) + { + if ($row['user_extended_struct_type'] == 0) + { // Its a category + $this->catDefinitions[$row['user_extended_struct_id']] = $row; + } + else + { // Its a field definition + $this->fieldDefinitions[$row['user_extended_struct_id']] = $row; + $this->nameIndex['user_'.$row['user_extended_struct_name']] = $row['user_extended_struct_id']; // Create name to ID index + if ($row['user_extended_struct_text'] == '_system_') + { + $this->systemCount++; + } + else + { + $this->userCount++; + } + } + } + } + } + + + + /** + * Check for reserved field names. + * (Names which clash with the 'normal' user table aren't allowed) + * + * @param string $name - name of field bweing checked (no 'user_' prefix) + * + * @return boolean TRUE if disallowed name + */ + public function user_extended_reserved($name) + { + return (in_array($name, $this->reserved_names)); + } + + + + // Adds the _FIELD_TYPES array to the data, ready for saving in the DB. + function addFieldTypes(&$target) + { + $target['_FIELD_TYPES'] = array(); // We should always want to recreate the array, even if it exists + foreach ($target['data'] as $k => $v) + { + if (isset($this->nameIndex[$k])) + { + switch ($this->fieldDefinitions[$this->nameIndex[$k]]['user_extended_struct_type']) + { + case EUF_TEXT : + case EUF_DB_FIELD : + case EUF_TEXTAREA : + case EUF_DROPDOWN : + case EUF_DATE : + case EUF_LANGUAGE : + case EUF_PREDEFINED : + case EUF_CHECKBOX : + case EUF_RADIO : + $target['_FIELD_TYPES'][$k] = 'todb'; + break; + + case EUF_INTEGER : + $target['_FIELD_TYPES'][$k] = 'int'; + break; + } + } + } + } + + + + /** + * For all UEFs not in the target array, adds the default value + * Also updates the _FIELD_TYPES array, so call this last thing before writing to the DB + * + * @param $target - pointer to data array + */ + public function addDefaultFields(&$target) + { + //$target['_FIELD_TYPES'] = array(); // We should always want to recreate the array, even if it exists + foreach ($this->fieldDefinitions as $k => $defs) + { + $f = 'user_'.$defs['user_extended_struct_name']; + if (!isset($target['data'][$f]) && $this->fieldDefinitions[$k]['user_extended_struct_default']) + { + switch ($this->fieldDefinitions[$k]['user_extended_struct_type']) + { + case EUF_TEXT : + case EUF_DB_FIELD : + case EUF_TEXTAREA : + case EUF_DROPDOWN : + case EUF_DATE : + case EUF_LANGUAGE : + case EUF_PREDEFINED : + + $target['data'][$f] = $this->fieldDefinitions[$k]['user_extended_struct_default']; + $target['_FIELD_TYPES'][$f] = 'todb'; + break; + case EUF_RADIO : + case EUF_INTEGER : + $target['data'][$f] = $this->fieldDefinitions[$k]['user_extended_struct_default']; + $target['_FIELD_TYPES'][$f] = 'int'; + break; + case EUF_CHECKBOX : + $target['data'][$f] = $this->fieldDefinitions[$k]['user_extended_struct_default']; + $target['_FIELD_TYPES'][$f] = 'array'; + break; + } + } + } + } + + + + // Validate a single extended user field + // $val is whatever the user entered. + // $params is the field definition + // Return FALSE if acceptable, TRUE if fail , error message on regex fail if the message is defined + function user_extended_validate_entry($val, $params) + { + global $tp; + $parms = explode('^,^', $params['user_extended_struct_parms']); + $requiredField = $params['user_extended_struct_required'] == 1; + $regex = $tp->toText($parms[1]); + $regexfail = $tp->toText($parms[2]); + if (defined($regexfail)) { $regexfail = constant($regexfail); } + if($val == '' && $requiredField) return TRUE; + switch ($type) + { + case EUF_DATE : + if ($requiredField && ($val == '0000-00-00')) return TRUE; + break; + } + if($regex != "" && $val != "") + { + if(!preg_match($regex, $val)) return $regexfail ? $regexfail : TRUE; + } + return FALSE; // Pass by default here + } + + + + /** + * Validate all user-modifable extended user fields which are presented. + * Primarily intended to validate data entered by a user or admin + * + * @param array $inArray is the input data (usually from $_POST or $_POST['ue'], although doesn't have to be) - may have 'surplus' values + * @param array $hideArray is a set of possible 'hide' flags + * @param boolean $isSignup TRUE causes required fields to be specifically checked, else only data passed is checked + * + * @return array with three potential subkeys: + * 'data' - valid data values (key is field name) + * ['data']['user_hidden_fields'] is the hidden fields + * 'errors' - data values in error + * 'errortext' - error message corresponding to erroneous value + * + * @todo - does $hidden_fields need to be merged with values for fields not processed? (Probably not - should only relate to fields current user can see) + * @todo - make sure admin can edit fields of other users + */ + public function userExtendedValidateAll($inArray, $hideArray, $isSignup=FALSE) + { + global $tp; + $eufVals = array(); // 'Answer' array + $hideFlags = array(); + + foreach ($this->fieldDefinitions as $k => $defs) + { + $category = $defs['user_extended_struct_parent']; + if (($category == 0) || ($isSignup && (int) $this->catDefinitions[$category]['user_extended_struct_applicable'] === (int) e_UC_MEMBER && (int) $this->catDefinitions[$category]['user_extended_struct_write'] === (int) e_UC_MEMBER) || (check_class($this->catDefinitions[$category]['user_extended_struct_applicable']) && check_class($this->catDefinitions[$category]['user_extended_struct_write']))) + { // Category applicable to user + + if (($isSignup && (int) $defs['user_extended_struct_applicable'] === (int) e_UC_MEMBER && (int) $defs['user_extended_struct_write'] === (int) e_UC_MEMBER) || (check_class($defs['user_extended_struct_applicable']) && check_class($defs['user_extended_struct_write']))) + { // User can also update field + $f = 'user_'.$defs['user_extended_struct_name']; + if (isset($inArray[$f]) || ($isSignup && ($defs['user_extended_struct_required'] == 1))) + { // Only allow valid keys + $val = varset($inArray[$f], FALSE); + $err = $this->user_extended_validate_entry($val, $defs); + if ($err === true) + { // General error - usually empty field; could be unacceptable value, or regex fail and no error message defined + $eufVals['errortext'][$f] = str_replace('--SOMETHING--',$tp->toHtml(defset($defs['user_extended_struct_text'], $defs['user_extended_struct_text']),FALSE,'defs'),LAN_USER_75); + $eufVals['errors'][$f] = ERR_GENERIC; + } + elseif ($err) + { // Specific error message returned - usually regex fail + $eufVals['errortext'][$f] = $err; + $eufVals['errors'][$f] = ERR_GENERIC; + } + elseif (!$err) + { + $eufVals['data'][$f] = $tp->toDB($val); + } + if (isset($hideArray[$f])) + { + $hideFlags[] = $f; + } + } + } + } + } + $hidden_fields = implode('^', $hideFlags); + if ($hidden_fields != '') + { + $hidden_fields = '^'.$hidden_fields.'^'; + } + $eufVals['data']['user_hidden_fields'] = $hidden_fields; + + return $eufVals; + } + + + + + function user_extended_get_categories($byID = TRUE) + { + $ret = array(); + global $sql; + if($sql->db_Select("user_extended_struct", "*", "user_extended_struct_type = 0 ORDER BY user_extended_struct_order ASC")) + { + if($byID == TRUE) + { + while($row = $sql->db_Fetch()) + { + $ret[$row['user_extended_struct_id']][] = $row; + } + } + else + { + $ret = $sql->db_getList(); + } + } + return $ret; + } + + + // Get the definition of all fields, or those in a specific category, grouped by category ID + // Reads non-system fields only + function user_extended_get_fields($cat = "") + { + global $sql; + $ret = array(); + $more = ($cat) ? " AND user_extended_struct_parent = ".intval($cat)." " : ""; + if($sql->db_Select("user_extended_struct", "*", "user_extended_struct_type > 0 AND user_extended_struct_text != '_system_' {$more} ORDER BY user_extended_struct_order ASC")) + { + while($row = $sql->db_Fetch(MYSQL_ASSOC)) + { + $ret[$row['user_extended_struct_parent']][] = $row; + } + } + return $ret; + } + + // Get the definition of all fields, or those in a specific category, indexed by field ID (or some other field by specifying $indexField) + function user_extended_get_fieldList($cat = "", $indexField = 'user_extended_struct_id') + { + global $sql; + $more = ($cat != '') ? " AND user_extended_struct_parent = ".intval($cat)." " : ""; + if($sql->db_Select("user_extended_struct", "*", "user_extended_struct_type > 0 AND user_extended_struct_text != '_system_' {$more} ORDER BY user_extended_struct_order ASC")) + { + while($row = $sql->db_Fetch(MYSQL_ASSOC)) + { + $ret[$row[$indexField]] = $row; + } + } + return $ret; + } + + + // Return the field creation text for a definition + function user_extended_type_text($type, $default) + { + global $tp; + if(!is_numeric($type)) + { + return false; + } + + switch ($type) + { + case EUF_INTEGER : + $db_type = 'INT(11)'; + break; + + case EUF_DATE : + $db_type = 'DATE NOT NULL'; + break; + + case EUF_TEXTAREA: + $db_type = 'TEXT'; + break; + + case EUF_TEXT : + case EUF_RADIO : + case EUF_DROPDOWN : + case EUF_DB_FIELD : + case EUF_LANGUAGE : + case EUF_PREDEFINED : + case EUF_CHECKBOX : + $db_type = 'VARCHAR(255)'; + break; + + case EUF_CATEGORY: + return ''; + break; + + default: + e107::getMessage()->addDebug("Unknown type '{$type}' for user extended field."); + return false; + break; + + } + if($type != EUF_DB_FIELD && $type != EUF_TEXTAREA && $default != '') + { + $default_text = " DEFAULT '".$tp -> toDB($default, true)."'"; + } + else + { + $default_text = ''; + } + return $db_type.$default_text; + } + + + function user_extended_field_exist($name) + { + global $sql, $tp; + return $sql->db_Count('user_extended_struct','(*)', "WHERE user_extended_struct_name = '".$tp -> toDB($name, true)."'"); + } + + function clear_cache() + { + $e107 = e107::getInstance(); + $e107->ecache->clear_sys('nomd5_extended_struct'); + } + + // For use by plugins to add extended user fields and won't be visible anywhere else + function user_extended_add_system($name, $type, $default = '', $source = '_system_') + { + return $this->user_extended_add($name, '_system_', $type, $source, '', $default, 0, 255, 255, 255, 0, 0); + } + + + function user_extended_add($name, $text, $type, $parms, $values, $default, $required, $read, $write, $applicable, $order='', $parent) + { + global $sql, $tp; + $this->clear_cache(); + if(is_array($name)) + { + extract($name); + } + if(!is_numeric($type)) + { + $type = $this->typeArray[$type]; + } + + if (!$this->user_extended_field_exist($name) && !$this->user_extended_reserved($name)) + { + $field_info = $this->user_extended_type_text($type, $default); + + // wrong type + if(false === $field_info) return false; + + if($order === '' && $field_info) + { + if($sql->db_Select('user_extended_struct','MAX(user_extended_struct_order) as maxorder','1')) + { + $row = $sql->db_Fetch(); + if(is_numeric($row['maxorder'])) + { + $order = $row['maxorder']+1; + } + } + } + // field of type category + if($field_info) + { + $sql->db_Select_gen('ALTER TABLE #user_extended ADD user_'.$tp -> toDB($name, true).' '.$field_info); + } + + $sql->db_Insert('user_extended_struct',"null,'".$tp -> toDB($name, true)."','".$tp -> toDB($text, true)."','".intval($type)."','".$tp -> toDB($parms, true)."','".$tp -> toDB($values, true)."', '".$tp -> toDB($default, true)."', '".intval($read)."', '".intval($write)."', '".intval($required)."', '0', '".intval($applicable)."', '".intval($order)."', '".intval($parent)."'"); + if ($this->user_extended_field_exist($name)) + { + return TRUE; + } + } + return FALSE; + } + + + + function user_extended_modify($id, $name, $text, $type, $parms, $values, $default, $required, $read, $write, $applicable, $parent) + { + global $sql, $tp; + if ($this->user_extended_field_exist($name)) + { + $field_info = $this->user_extended_type_text($type, $default); + // wrong type + if(false === $field_info) return false; + + // field of type category + if($field_info) + { + $sql->db_Select_gen("ALTER TABLE #user_extended MODIFY user_".$tp -> toDB($name, true)." ".$field_info); + } + + $newfield_info = " + user_extended_struct_text = '".$tp -> toDB($text, true)."', + user_extended_struct_type = '".intval($type)."', + user_extended_struct_parms = '".$tp -> toDB($parms, true)."', + user_extended_struct_values = '".$tp -> toDB($values, true)."', + user_extended_struct_default = '".$tp -> toDB($default, true)."', + user_extended_struct_required = '".intval($required)."', + user_extended_struct_read = '".intval($read)."', + user_extended_struct_write = '".intval($write)."', + user_extended_struct_applicable = '".intval($applicable)."', + user_extended_struct_parent = '".intval($parent)."' + WHERE user_extended_struct_id = '".intval($id)."' + "; + return $sql->db_Update("user_extended_struct", $newfield_info); + } + } + + function user_extended_remove($id, $name) + { + global $sql, $tp; + $this->clear_cache(); + if ($this->user_extended_field_exist($name)) + { + // FIXME - no table structure changes for categories + // but no good way to detect it right now - ignore the sql error for now, fix it asap + $sql->db_Select_gen("ALTER TABLE #user_extended DROP user_".$tp -> toDB($name, true)); + + if(is_numeric($id)) + { + $sql->db_Delete("user_extended_struct", "user_extended_struct_id = '".intval($id)."' "); + } + else + { + $sql->db_Delete("user_extended_struct", "user_extended_struct_name = '".$tp -> toDB($id, true)."' "); + } + return !($this->user_extended_field_exist($name)); + } + } + + function user_extended_hide($struct, $curval) + { + $chk = ($curval) ? " checked='checked' " : ""; + $name = "hide[user_".$struct['user_extended_struct_name']."]"; + return " ".UE_LAN_HIDE; + } + + + + function user_extended_edit($struct, $curval) + { + global $tp; + if(trim($curval) == "" && $struct['user_extended_struct_default'] != "") + { + $curval = $struct['user_extended_struct_default']; + } + $choices = explode(",",$struct['user_extended_struct_values']); + foreach($choices as $k => $v) + { + $choices[$k] = str_replace("[E_COMMA]", ",", $choices[$k]); + } + $parms = explode("^,^",$struct['user_extended_struct_parms']); + $include = preg_replace("/\n/", " ", $tp->toHtml($parms[0])); + $regex = $tp->toText($parms[1]); + $regexfail = $tp->toText($parms[2]); + $fname = "ue[user_".$struct['user_extended_struct_name']."]"; + if(strpos($include, 'class') === FALSE) + { + $include .= " class='tbox' "; + } + + + switch($struct['user_extended_struct_type']) + { + case EUF_TEXT : //textbox + case EUF_INTEGER : //integer + $ret = ""; + return $ret; + break; + + case EUF_RADIO : //radio + $ret = ''; + foreach($choices as $choice) + { + $choice = trim($choice); + $choice = deftrue($choice, $choice); + $chk = ($curval == $choice)? " checked='checked' " : ""; + $ret .= " {$choice}"; + } + return $ret; + break; + + case EUF_CHECKBOX : //checkboxes + foreach($choices as $choice) + { + $choice = trim($choice); + if(strpos($choice,"|")!==FALSE) + { + list($val,$label) = explode("|",$choice); + } + else + { + $val = $choice; + $label = $choice; + } + $label = deftrue($label, $label); + $chk = ($curval == $val)? " checked='checked' " : ""; + $ret .= " {$label}
"; + } + return $ret; + break; + + case EUF_DROPDOWN : //dropdown + $ret = "\n"; + return $ret; + break; + + case EUF_PREDEFINED : // predefined list, shown in dropdown + $listRoot = trim($struct['user_extended_struct_values']); // Base list name + $filename = e_ADMIN.'sql/extended_'.$listRoot.'.php'; + if (!is_readable($filename)) return 'No file: '.$filename; + require_once($filename); + $className = 'extended_'.$listRoot; + if (!class_exists($className)) return '?????'; + $temp = new $className(); + if (!method_exists($className, 'getValue')) return '???-???'; + $temp->pointerReset(); + + $ret = "\n"; + return $ret; + + case EUF_DB_FIELD : //db_field + global $sql; + $order = ($choices[3]) ? "ORDER BY ".$tp -> toDB($choices[3], true) : ""; + + if($sql->db_Select($tp -> toDB($choices[0], true), $tp -> toDB($choices[1], true).",".$tp -> toDB($choices[2], true), "1 $order")){ + $choiceList = $sql->db_getList('ALL',FALSE); + $ret = "\n"; + return $ret; + } else { + return ""; + } + break; + + case EUF_TEXTAREA : //textarea + return ""; + break; + + case EUF_DATE : //date + return e107::getForm()->datepicker($fname,$curval,'dateformat=yy-mm-dd'); + break; + + case EUF_LANGUAGE : // language + require_once(e_HANDLER."file_class.php"); + $fl = new e_file; + $lanlist = $fl->get_dirs(e_LANGUAGEDIR); + sort($lanlist); + $ret = "\n"; + break; + + } + + return $ret; + } + + function user_extended_getStruct($orderby="user_extended_struct_order") + { + if($ueStruct = getcachedvars('ue_struct')) + { + return $ueStruct; + } + global $tp; + $ret = array(); + $parms = ""; + if($orderby != "") + { + $parms = "1 ORDER BY ".$tp -> toDB($orderby, true); + } + $sql_ue = new db; // Use our own db to avoid interference with other objects + if($sql_ue->db_Select('user_extended_struct','*',$parms)) + { + while($row = $sql_ue->db_Fetch()) + { + $ret['user_'.$row['user_extended_struct_name']] = $row; + } + } + cachevars('ue_struct',$ret); + return $ret; + } + + + function parse_extended_xml($contents, $no_cache = FALSE) + { + if($no_cache == FALSE && $this->extended_xml) + { + return $this->extended_xml; + } + + $xml = e107::getXml(); + $data = $xml->loadXMLfile(e_CORE."xml/user_extended.xml", true); + $ret['version'] = $data['@attributes']['version']; + unset($info); + foreach($data['item'] as $item) + { + if(is_array($item['include_text']) && !count($item['include_text'])) + { + $item['include_text'] = ''; + } + $info = array( + "name" => $item['@attributes']['name'], + "text" => "UE_LAN_".strtoupper($item['@attributes']['name']), + "type" => $item['type'], + "values" => $item['values'], + "default" => $item['default'], + "required" => $item['required'], + "read" => $item['read'], + "write" => $item['write'], + "applicable" => $item['applicable'], + "include_text" => $item['include_text'], + "parms" => $item['include_text'], + "regex" => $item['regex'] + ); + if(is_array($item['default']) && $item['default'] == '') + { + $info['default'] = 0; + } + if($item['regex']) + { + $info['parms'] .= $item['include_text']."^,^".$item['regex']."^,^LAN_UE_FAIL_".strtoupper($item['@attributes']['name']); + } + $ret[$item['@attributes']['name']] = $info; + } + $this->extended_xml = $ret; + return $this->extended_xml; + } + + /** + * Proxy Method to retrieve the value of an extended field + * @param int $uid + * @param var $field_name + * @param object $ifnotset [optional] + * @return mixed + */ + function get($uid, $field_name, $ifnotset=false) + { + return user_extended_getvalue($uid, $field_name, $ifnotset); + } + + + + /** + * Proxy method for setting the value of an extended field + * (inserts or updates) + * + * @param integer $uid + * @param string $field_name eg. location + * @param string $newvalue eg. USA + * @param string $fieldType [optional] default 'todb' | + * @return boolean; + */ + function set($uid, $field_name, $newvalue, $fieldType = 'todb') + { + return $this->user_extended_setvalue($uid, $field_name, $newvalue, $fieldType); + } + + + /** + * Set the value of an extended field + * + * $ue = new e107_user_extended; + * $result = $ue->user_extended_setvalue(1, 'location', 'Pittsburgh'); + * + * + */ + function user_extended_setvalue($uid, $field_name, $newvalue, $fieldType = 'todb') + { + $sql = e107::getDb(); + $tp = e107::getParser(); + + $uid = (int)$uid; + switch($fieldType) + { + case 'int': + $newvalue = (int)$newvalue; + break; + + case 'escape': + $newvalue = "'".mysql_real_escape_string($newvalue)."'"; + break; + + default: + $newvalue = "'".$tp->toDB($newvalue)."'"; + break; + } + if(substr($field_name, 0, 5) != 'user_') + { + $field_name = 'user_'.$field_name; + } + $qry = " + INSERT INTO `#user_extended` (user_extended_id, {$field_name}) + VALUES ({$uid}, {$newvalue}) + ON DUPLICATE KEY UPDATE {$field_name} = {$newvalue} + "; + return $sql->db_Select_gen($qry); + } + + + /** + * Retrieve the value of an extended field + * + * $ue = new e107_user_extended; + * $value = $ue->user_extended_getvalue(2, 'location'); + * + */ + function user_extended_getvalue($uid, $field_name, $ifnotset=false) + { + $uid = intval($uid); + if(substr($field_name, 0, 5) != 'user_') + { + $field_name = 'user_'.$field_name; + } + $uinfo = get_user_data($uid); + if (!isset($uinfo[$field_name])) return $ifnotset; + return $uinfo[$field_name]; + } + + + /** + * Given a predefined list field, returns the display text corresponding to the passed value + * + * @TODO: consider whether to cache the class object + */ + function user_extended_display_text($table, $value) + { + $filename = e_ADMIN.'sql/extended_'.$table.'.php'; + if (!is_readable($filename)) return 'No file: '.$filename; + require_once($filename); + $className = 'extended_'.$table; + if (!class_exists($className)) return '?????'; + $temp = new $className(); + if (!method_exists($className, 'getValue')) return '???-???'; + return $temp->getValue($value); + } + +} ?> \ No newline at end of file