PageRenderTime 45ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/e107_handlers/user_extended_class.php

https://github.com/CasperGemini/e107
PHP | 1060 lines | 759 code | 154 blank | 147 comment | 133 complexity | 493957c0f8ed6f43074383643a7f4d47 MD5 | raw file
Possible License(s): GPL-2.0
  1. <?php
  2. /*
  3. * e107 website system
  4. *
  5. * Copyright (C) 2008-2012 e107 Inc (e107.org)
  6. * Released under the terms and conditions of the
  7. * GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
  8. *
  9. * Extended user field handler
  10. *
  11. * $URL$
  12. * $Id$
  13. *
  14. */
  15. if (!defined('e107_INIT')) { exit; }
  16. /**
  17. * @package e107
  18. * @subpackage e107_handlers
  19. * @version $Id$;
  20. *
  21. * Extended user field handler
  22. *
  23. * @todo: - change some routines to access the cached variables rather than DB
  24. * @todo: Remove setting up of _FIELD_TYPES array (may be necessary, since UEF data structure not fixed)
  25. * @todo: Consider changing field type constants to class constants
  26. * @todo - cache field structure (already done in a different way in get_user_data() in class2.php line 1387 or so)
  27. * @todo - class variables - confirm whether public/protected assignments are correct
  28. * @todo - consider whether to split system and non-system fields
  29. Code uses two tables:
  30. user_extended_struct - individual field definitions, one record per field
  31. user_extended - actual field data, one record per user
  32. @todo: Should user_extended_validate_entry() check DB for DB-type fields?
  33. */
  34. e107::coreLan('user_extended');
  35. class e107_user_extended
  36. {
  37. public $user_extended_types; // Text description corresponding to each field type
  38. private $extended_xml = FALSE;
  39. public $typeArray; // Cross-reference between names of field types, and numeric ID (must be public)
  40. private $reserved_names; // List of field names used in main user DB - not allowed in extended DB
  41. public $fieldDefinitions; // Array initialised from DB by constructor - currently all fields
  42. public $catDefinitions; // Categories
  43. private $nameIndex; // Array for field name lookup - initialised by constructor
  44. public $systemCount = 0; // Count of system fields - always zero ATM
  45. public $userCount = 0; // Count of non-system fields
  46. public function __construct()
  47. {
  48. define('EUF_CATEGORY', 0);
  49. define('EUF_TEXT',1);
  50. define('EUF_RADIO',2);
  51. define('EUF_DROPDOWN',3);
  52. define('EUF_DB_FIELD',4);
  53. define('EUF_TEXTAREA',5);
  54. define('EUF_INTEGER',6);
  55. define('EUF_DATE',7);
  56. define('EUF_LANGUAGE',8);
  57. define('EUF_PREDEFINED',9); // should be EUF_LIST IMO
  58. define('EUF_CHECKBOX',10);
  59. define('EUF_PREFIELD',11); // should be EUF_PREDEFINED, useful when creating fields from e.g. plugin XML
  60. $this->typeArray = array(
  61. 'text' => 1,
  62. 'radio' => 2,
  63. 'dropdown' => 3,
  64. 'db field' => 4,
  65. 'textarea' => 5,
  66. 'integer' => 6,
  67. 'date' => 7,
  68. 'language' => 8,
  69. 'list' => 9,
  70. 'checkbox' => 10,
  71. 'predefined' => 11, // DON'T USE IT IN PREDEFINED FIELD XML!!! Used in plugin installation routine.
  72. );
  73. $this->user_extended_types = array(
  74. 1 => UE_LAN_1,
  75. 2 => UE_LAN_2,
  76. 3 => UE_LAN_3,
  77. 4 => UE_LAN_4,
  78. 5 => UE_LAN_5,
  79. 6 => UE_LAN_6,
  80. 7 => UE_LAN_7,
  81. 8 => UE_LAN_8,
  82. 9 => UE_LAN_9,
  83. 10=> UE_LAN_10
  84. );
  85. //load array with field names from main user table, so we can disallow these
  86. // user_new, user_timezone deleted for 0.8
  87. $this->reserved_names = array (
  88. 'id', 'name', 'loginname', 'customtitle', 'password',
  89. 'sess', 'email', 'signature', 'image', 'hideemail',
  90. 'join', 'lastvisit', 'currentvisit', 'chats',
  91. 'comments', 'forums', 'ip', 'ban', 'prefs', 'viewed',
  92. 'visits', 'admin', 'login', 'class', 'baseclasslist', 'perms', 'pwchange',
  93. 'xup'
  94. );
  95. $sql = e107::getDB();
  96. // Read in all the field and category fields
  97. // At present we load all fields into common array - may want to split system and non-system
  98. $this ->catDefinitions = array(); // Categories array
  99. $this->fieldDefinitions = array(); // Field definitions array
  100. $this->nameIndex = array(); // Index of names => field IDs
  101. $this->systemCount = 0;
  102. $this->userCount = 0;
  103. if($sql->db_Select('user_extended_struct', '*', "user_extended_struct_text != '_system_' ORDER BY user_extended_struct_order ASC"))
  104. {
  105. while($row = $sql->db_Fetch(MYSQL_ASSOC))
  106. {
  107. if ($row['user_extended_struct_type'] == 0)
  108. { // Its a category
  109. $this->catDefinitions[$row['user_extended_struct_id']] = $row;
  110. }
  111. else
  112. { // Its a field definition
  113. $this->fieldDefinitions[$row['user_extended_struct_id']] = $row;
  114. $this->nameIndex['user_'.$row['user_extended_struct_name']] = $row['user_extended_struct_id']; // Create name to ID index
  115. if ($row['user_extended_struct_text'] == '_system_')
  116. {
  117. $this->systemCount++;
  118. }
  119. else
  120. {
  121. $this->userCount++;
  122. }
  123. }
  124. }
  125. }
  126. }
  127. /**
  128. * Check for reserved field names.
  129. * (Names which clash with the 'normal' user table aren't allowed)
  130. *
  131. * @param string $name - name of field bweing checked (no 'user_' prefix)
  132. *
  133. * @return boolean TRUE if disallowed name
  134. */
  135. public function user_extended_reserved($name)
  136. {
  137. return (in_array($name, $this->reserved_names));
  138. }
  139. // Adds the _FIELD_TYPES array to the data, ready for saving in the DB.
  140. function addFieldTypes(&$target)
  141. {
  142. $target['_FIELD_TYPES'] = array(); // We should always want to recreate the array, even if it exists
  143. foreach ($target['data'] as $k => $v)
  144. {
  145. if (isset($this->nameIndex[$k]))
  146. {
  147. switch ($this->fieldDefinitions[$this->nameIndex[$k]]['user_extended_struct_type'])
  148. {
  149. case EUF_TEXT :
  150. case EUF_DB_FIELD :
  151. case EUF_TEXTAREA :
  152. case EUF_DROPDOWN :
  153. case EUF_DATE :
  154. case EUF_LANGUAGE :
  155. case EUF_PREDEFINED :
  156. case EUF_CHECKBOX :
  157. case EUF_RADIO :
  158. $target['_FIELD_TYPES'][$k] = 'todb';
  159. break;
  160. case EUF_INTEGER :
  161. $target['_FIELD_TYPES'][$k] = 'int';
  162. break;
  163. }
  164. }
  165. }
  166. }
  167. /**
  168. * For all UEFs not in the target array, adds the default value
  169. * Also updates the _FIELD_TYPES array, so call this last thing before writing to the DB
  170. *
  171. * @param $target - pointer to data array
  172. */
  173. public function addDefaultFields(&$target)
  174. {
  175. //$target['_FIELD_TYPES'] = array(); // We should always want to recreate the array, even if it exists
  176. foreach ($this->fieldDefinitions as $k => $defs)
  177. {
  178. $f = 'user_'.$defs['user_extended_struct_name'];
  179. if (!isset($target['data'][$f]) && $this->fieldDefinitions[$k]['user_extended_struct_default'])
  180. {
  181. switch ($this->fieldDefinitions[$k]['user_extended_struct_type'])
  182. {
  183. case EUF_TEXT :
  184. case EUF_DB_FIELD :
  185. case EUF_TEXTAREA :
  186. case EUF_DROPDOWN :
  187. case EUF_DATE :
  188. case EUF_LANGUAGE :
  189. case EUF_PREDEFINED :
  190. $target['data'][$f] = $this->fieldDefinitions[$k]['user_extended_struct_default'];
  191. $target['_FIELD_TYPES'][$f] = 'todb';
  192. break;
  193. case EUF_RADIO :
  194. case EUF_INTEGER :
  195. $target['data'][$f] = $this->fieldDefinitions[$k]['user_extended_struct_default'];
  196. $target['_FIELD_TYPES'][$f] = 'int';
  197. break;
  198. case EUF_CHECKBOX :
  199. $target['data'][$f] = $this->fieldDefinitions[$k]['user_extended_struct_default'];
  200. $target['_FIELD_TYPES'][$f] = 'array';
  201. break;
  202. }
  203. }
  204. }
  205. }
  206. // Validate a single extended user field
  207. // $val is whatever the user entered.
  208. // $params is the field definition
  209. // Return FALSE if acceptable, TRUE if fail , error message on regex fail if the message is defined
  210. function user_extended_validate_entry($val, $params)
  211. {
  212. $tp = e107::getParser();
  213. $parms = explode('^,^', $params['user_extended_struct_parms']);
  214. $requiredField = $params['user_extended_struct_required'] == 1;
  215. $regex = $tp->toText($parms[1]);
  216. $regexfail = $tp->toText($parms[2]);
  217. if (defined($regexfail)) { $regexfail = constant($regexfail); }
  218. if($val == '' && $requiredField) return TRUE;
  219. switch ($type)
  220. {
  221. case EUF_DATE :
  222. if ($requiredField && ($val == '0000-00-00')) return TRUE;
  223. break;
  224. }
  225. if($regex != "" && $val != "")
  226. {
  227. if(!preg_match($regex, $val)) return $regexfail ? $regexfail : TRUE;
  228. }
  229. return FALSE; // Pass by default here
  230. }
  231. /**
  232. * Validate all user-modifable extended user fields which are presented.
  233. * Primarily intended to validate data entered by a user or admin
  234. *
  235. * @param array $inArray is the input data (usually from $_POST or $_POST['ue'], although doesn't have to be) - may have 'surplus' values
  236. * @param array $hideArray is a set of possible 'hide' flags
  237. * @param boolean $isSignup TRUE causes required fields to be specifically checked, else only data passed is checked
  238. *
  239. * @return array with three potential subkeys:
  240. * 'data' - valid data values (key is field name)
  241. * ['data']['user_hidden_fields'] is the hidden fields
  242. * 'errors' - data values in error
  243. * 'errortext' - error message corresponding to erroneous value
  244. *
  245. * @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)
  246. * @todo - make sure admin can edit fields of other users
  247. */
  248. public function userExtendedValidateAll($inArray, $hideArray, $isSignup=FALSE)
  249. {
  250. $tp = e107::getParser();
  251. $eufVals = array(); // 'Answer' array
  252. $hideFlags = array();
  253. foreach ($this->fieldDefinitions as $k => $defs)
  254. {
  255. $category = $defs['user_extended_struct_parent'];
  256. 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'])))
  257. { // Category applicable to user
  258. 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'])))
  259. { // User can also update field
  260. $f = 'user_'.$defs['user_extended_struct_name'];
  261. if (isset($inArray[$f]) || ($isSignup && ($defs['user_extended_struct_required'] == 1)))
  262. { // Only allow valid keys
  263. $val = varset($inArray[$f], FALSE);
  264. $err = $this->user_extended_validate_entry($val, $defs);
  265. if ($err === true)
  266. { // General error - usually empty field; could be unacceptable value, or regex fail and no error message defined
  267. $eufVals['errortext'][$f] = str_replace('--SOMETHING--',$tp->toHtml(defset($defs['user_extended_struct_text'], $defs['user_extended_struct_text']),FALSE,'defs'),LAN_USER_75);
  268. $eufVals['errors'][$f] = ERR_GENERIC;
  269. }
  270. elseif ($err)
  271. { // Specific error message returned - usually regex fail
  272. $eufVals['errortext'][$f] = $err;
  273. $eufVals['errors'][$f] = ERR_GENERIC;
  274. }
  275. elseif (!$err)
  276. {
  277. $eufVals['data'][$f] = $tp->toDB($val);
  278. }
  279. if (isset($hideArray[$f]))
  280. {
  281. $hideFlags[] = $f;
  282. }
  283. }
  284. }
  285. }
  286. }
  287. $hidden_fields = implode('^', $hideFlags);
  288. if ($hidden_fields != '')
  289. {
  290. $hidden_fields = '^'.$hidden_fields.'^';
  291. }
  292. $eufVals['data']['user_hidden_fields'] = $hidden_fields;
  293. return $eufVals;
  294. }
  295. /**
  296. * alias of user_extended_get_categories();
  297. *
  298. */
  299. function getCategories($byID = TRUE)
  300. {
  301. return $this->user_extended_get_categories($byID);
  302. }
  303. function user_extended_get_categories($byID = TRUE)
  304. {
  305. $ret = array();
  306. $sql = e107::getDb('ue');
  307. if($sql->db_Select("user_extended_struct", "*", "user_extended_struct_type = 0 ORDER BY user_extended_struct_order ASC"))
  308. {
  309. if($byID == TRUE)
  310. {
  311. while($row = $sql->fetch())
  312. {
  313. $ret[$row['user_extended_struct_id']][] = $row;
  314. }
  315. }
  316. else
  317. {
  318. $ret = $sql->db_getList();
  319. }
  320. }
  321. return $ret;
  322. }
  323. /**
  324. * BC Alias of getFields();
  325. */
  326. function getFields($cat = "")
  327. {
  328. return $this->user_extended_get_fieldList($cat);
  329. }
  330. // Get the definition of all fields, or those in a specific category, grouped by category ID
  331. // Reads non-system fields only
  332. function user_extended_get_fields($cat = "")
  333. {
  334. $sql = e107::getDb('ue');
  335. $ret = array();
  336. $more = ($cat) ? " AND user_extended_struct_parent = ".intval($cat)." " : "";
  337. if($sql->select("user_extended_struct", "*", "user_extended_struct_type > 0 AND user_extended_struct_text != '_system_' {$more} ORDER BY user_extended_struct_order ASC"))
  338. {
  339. while($row = $sql->fetch(MYSQL_ASSOC))
  340. {
  341. $ret[$row['user_extended_struct_parent']][] = $row;
  342. }
  343. }
  344. return $ret;
  345. }
  346. /**
  347. * Alias of getFieldList().
  348. *
  349. */
  350. function getFieldList($cat = "", $indexField = 'user_extended_struct_id')
  351. {
  352. return $this->user_extended_get_fieldList($cat, $indexField);
  353. }
  354. /**
  355. * Get the definition of all fields, or those in a specific category, indexed by field ID (or some other field by specifying $indexField)
  356. * @param $cat
  357. * @param $indexField;
  358. * @param $system - include system fields.
  359. */
  360. function user_extended_get_fieldList($cat = "", $indexField = 'user_extended_struct_id', $system = false)
  361. {
  362. if(!$indexField)
  363. {
  364. $indexField = 'user_extended_struct_id';
  365. }
  366. $sql = e107::getDb('ue');
  367. $more = ($cat != '') ? " AND user_extended_struct_parent = ".intval($cat)." " : "";
  368. $sys = ($system == false) ? " AND user_extended_struct_text != '_system_' " : "";
  369. if($sql->select("user_extended_struct", "*", "user_extended_struct_type > 0 {$sys} {$more} ORDER BY user_extended_struct_order ASC"))
  370. {
  371. while($row = $sql->fetch(MYSQL_ASSOC))
  372. {
  373. $ret[$row[$indexField]] = $row;
  374. }
  375. }
  376. return $ret;
  377. }
  378. /**
  379. * Return the list of user_extended fields.
  380. * @return array
  381. */
  382. function getFieldNames()
  383. {
  384. $ret = array();
  385. $sql = e107::getDb('ue');
  386. if($sql->select("user_extended_struct", "*", "user_extended_struct_type > 0 ORDER BY user_extended_struct_order ASC"))
  387. {
  388. while($row = $sql->fetch(MYSQL_ASSOC))
  389. {
  390. $ret[] = 'user_'.$row['user_extended_struct_name'];
  391. }
  392. }
  393. return $ret;
  394. }
  395. // Return the field creation text for a definition
  396. function user_extended_type_text($type, $default)
  397. {
  398. $tp = e107::getParser();
  399. if(!is_numeric($type))
  400. {
  401. return false;
  402. }
  403. switch ($type)
  404. {
  405. case EUF_INTEGER :
  406. $db_type = 'INT(11)';
  407. break;
  408. case EUF_DATE :
  409. $db_type = 'DATE NOT NULL';
  410. break;
  411. case EUF_TEXTAREA:
  412. $db_type = 'TEXT';
  413. break;
  414. case EUF_TEXT :
  415. case EUF_RADIO :
  416. case EUF_DROPDOWN :
  417. case EUF_DB_FIELD :
  418. case EUF_LANGUAGE :
  419. case EUF_PREDEFINED :
  420. case EUF_CHECKBOX :
  421. $db_type = 'VARCHAR(255)';
  422. break;
  423. case EUF_CATEGORY:
  424. return '';
  425. break;
  426. default:
  427. e107::getMessage()->addDebug("<strong>Unknown type '{$type}' for user extended field.</strong>");
  428. return false;
  429. break;
  430. }
  431. if($type != EUF_DB_FIELD && $type != EUF_TEXTAREA && $default != '')
  432. {
  433. $default_text = " DEFAULT '".$tp -> toDB($default, true)."'";
  434. }
  435. else
  436. {
  437. $default_text = '';
  438. }
  439. return $db_type.$default_text;
  440. }
  441. function user_extended_field_exist($name)
  442. {
  443. $sql = e107::getDb('sql2');
  444. $tp = e107::getParser();
  445. return $sql->count('user_extended_struct','(*)', "WHERE user_extended_struct_name = '".$tp -> toDB($name, true)."'");
  446. }
  447. function clear_cache()
  448. {
  449. $e107 = e107::getInstance();
  450. $e107->ecache->clear_sys('nomd5_extended_struct');
  451. }
  452. // For use by plugins to add extended user fields and won't be visible anywhere else
  453. function user_extended_add_system($name, $type, $default = '', $source = '_system_')
  454. {
  455. return $this->user_extended_add($name, '_system_', $type, $source, '', $default, 0, 255, 255, 255, 0, 0);
  456. }
  457. function user_extended_add($name, $text, $type, $parms, $values, $default, $required, $read, $write, $applicable, $order='', $parent)
  458. {
  459. $sql = e107::getDb('ue');
  460. $tp = e107::getParser();
  461. $this->clear_cache();
  462. if(is_array($name))
  463. {
  464. extract($name);
  465. }
  466. if(!is_numeric($type))
  467. {
  468. $type = $this->typeArray[$type];
  469. }
  470. if($this->user_extended_field_exist($name))
  471. {
  472. return TRUE;
  473. }
  474. if (!$this->user_extended_reserved($name))
  475. {
  476. $field_info = $this->user_extended_type_text($type, $default);
  477. // wrong type
  478. if(false === $field_info) return false;
  479. if($order === '' && $field_info)
  480. {
  481. if($sql->select('user_extended_struct','MAX(user_extended_struct_order) as maxorder','1'))
  482. {
  483. $row = $sql->fetch();
  484. if(is_numeric($row['maxorder']))
  485. {
  486. $order = $row['maxorder']+1;
  487. }
  488. }
  489. }
  490. // field of type category
  491. if($field_info)
  492. {
  493. $sql->gen('ALTER TABLE #user_extended ADD user_'.$tp -> toDB($name, true).' '.$field_info);
  494. }
  495. $sql->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)."'");
  496. if ($this->user_extended_field_exist($name))
  497. {
  498. return TRUE;
  499. }
  500. }
  501. return FALSE;
  502. }
  503. function user_extended_modify($id, $name, $text, $type, $parms, $values, $default, $required, $read, $write, $applicable, $parent)
  504. {
  505. $sql = e107::getDb('ue');
  506. $tp = e107::getParser();
  507. if ($this->user_extended_field_exist($name))
  508. {
  509. $field_info = $this->user_extended_type_text($type, $default);
  510. // wrong type
  511. if(false === $field_info) return false;
  512. // field of type category
  513. if($field_info)
  514. {
  515. $sql->db_Select_gen("ALTER TABLE #user_extended MODIFY user_".$tp -> toDB($name, true)." ".$field_info);
  516. }
  517. $newfield_info = "
  518. user_extended_struct_text = '".$tp -> toDB($text, true)."',
  519. user_extended_struct_type = '".intval($type)."',
  520. user_extended_struct_parms = '".$tp -> toDB($parms, true)."',
  521. user_extended_struct_values = '".$tp -> toDB($values, true)."',
  522. user_extended_struct_default = '".$tp -> toDB($default, true)."',
  523. user_extended_struct_required = '".intval($required)."',
  524. user_extended_struct_read = '".intval($read)."',
  525. user_extended_struct_write = '".intval($write)."',
  526. user_extended_struct_applicable = '".intval($applicable)."',
  527. user_extended_struct_parent = '".intval($parent)."'
  528. WHERE user_extended_struct_id = '".intval($id)."'
  529. ";
  530. return $sql->db_Update("user_extended_struct", $newfield_info);
  531. }
  532. }
  533. function user_extended_remove($id, $name)
  534. {
  535. $sql = e107::getDb('ue');
  536. $tp = e107::getParser();
  537. $this->clear_cache();
  538. if ($this->user_extended_field_exist($name))
  539. {
  540. // FIXME - no table structure changes for categories
  541. // but no good way to detect it right now - ignore the sql error for now, fix it asap
  542. $sql->db_Select_gen("ALTER TABLE #user_extended DROP user_".$tp -> toDB($name, true));
  543. if(is_numeric($id))
  544. {
  545. $sql->db_Delete("user_extended_struct", "user_extended_struct_id = '".intval($id)."' ");
  546. }
  547. else
  548. {
  549. $sql->db_Delete("user_extended_struct", "user_extended_struct_name = '".$tp -> toDB($id, true)."' ");
  550. }
  551. return !($this->user_extended_field_exist($name));
  552. }
  553. }
  554. function user_extended_hide($struct, $curval)
  555. {
  556. $chk = ($curval) ? " checked='checked' " : "";
  557. $name = "hide[user_".$struct['user_extended_struct_name']."]";
  558. return "<input type='checkbox' {$chk} value='1' name='{$name}' />&nbsp;".UE_LAN_HIDE;
  559. }
  560. function user_extended_edit($struct, $curval)
  561. {
  562. $tp = e107::getParser();
  563. $frm = e107::getForm();
  564. if(trim($curval) == "" && $struct['user_extended_struct_default'] != "")
  565. {
  566. $curval = $struct['user_extended_struct_default'];
  567. }
  568. $choices = explode(",",$struct['user_extended_struct_values']);
  569. foreach($choices as $k => $v)
  570. {
  571. $choices[$k] = str_replace("[E_COMMA]", ",", $v);
  572. }
  573. $parms = explode("^,^",$struct['user_extended_struct_parms']);
  574. $include = preg_replace("/\n/", " ", $tp->toHtml($parms[0]));
  575. $regex = $tp->toText($parms[1]);
  576. $regexfail = $tp->toText($parms[2]);
  577. $fname = "ue[user_".$struct['user_extended_struct_name']."]";
  578. if(strpos($include, 'class') === FALSE)
  579. {
  580. $include .= " class='tbox' ";
  581. }
  582. switch($struct['user_extended_struct_type'])
  583. {
  584. case EUF_TEXT : //textbox
  585. case EUF_INTEGER : //integer
  586. $ret = "<input name='{$fname}' value='{$curval}' {$include} />";
  587. return $ret;
  588. break;
  589. case EUF_RADIO : //radio
  590. $ret = '';
  591. foreach($choices as $choice)
  592. {
  593. $choice = trim($choice);
  594. if(strpos($choice,"|")!==FALSE)
  595. {
  596. list($val,$label) = explode("|",$choice);
  597. }
  598. elseif(strpos($choice," => ")!==FALSE) // new in v2.x
  599. {
  600. list($val,$label) = explode(" => ",$choice);
  601. }
  602. else
  603. {
  604. $val = $choice;
  605. $label = $choice;
  606. }
  607. $label = deftrue($label, $label);
  608. if(deftrue('BOOTSTRAP'))
  609. {
  610. $ret .= $frm->radio($fname,$val,($curval == $val),array('label'=>$label));
  611. }
  612. else
  613. {
  614. $chk = ($curval == $val)? " checked='checked' " : "";
  615. $ret .= "<input {$include} type='radio' name='{$fname}' value='{$val}' {$chk} /> {$label}";
  616. }
  617. }
  618. return $ret;
  619. break;
  620. case EUF_CHECKBOX : //checkboxes
  621. foreach($choices as $choice)
  622. {
  623. $choice = trim($choice);
  624. if(strpos($choice,"|")!==FALSE)
  625. {
  626. list($val,$label) = explode("|",$choice);
  627. }
  628. elseif(strpos($choice," => ")!==FALSE) // new in v2.x
  629. {
  630. list($val,$label) = explode(" => ",$choice);
  631. }
  632. else
  633. {
  634. $val = $choice;
  635. $label = $choice;
  636. }
  637. $label = deftrue($label, $label);
  638. if(deftrue('BOOTSTRAP'))
  639. {
  640. $ret .= $frm->checkbox($fname,$val,($curval == $val),array('label'=>$label));
  641. }
  642. else
  643. {
  644. $chk = ($curval == $val)? " checked='checked' " : "";
  645. $ret .= "<input {$include} type='checkbox' name='{$fname}[]' value='{$val}' {$chk} /> {$label}<br />";
  646. }
  647. }
  648. return $ret;
  649. break;
  650. case EUF_DROPDOWN : //dropdown
  651. $ret = "<select {$include} name='{$fname}'>\n";
  652. $ret .= "<option value=''>&nbsp;</option>\n"; // ensures that the user chose it.
  653. foreach($choices as $choice)
  654. {
  655. $choice = trim($choice);
  656. $choice = deftrue($choice, $choice);
  657. $sel = ($curval == $choice) ? " selected='selected' " : "";
  658. $ret .= "<option value='{$choice}' {$sel}>{$choice}</option>\n";
  659. }
  660. $ret .= "</select>\n";
  661. return $ret;
  662. break;
  663. case EUF_PREDEFINED : // predefined list, shown in dropdown
  664. $listRoot = trim($struct['user_extended_struct_values']); // Base list name
  665. $filename = e_CORE.'sql/extended_'.$listRoot.'.php';
  666. if (!is_readable($filename)) return 'No file: '.$filename;
  667. require_once($filename);
  668. $className = 'extended_'.$listRoot;
  669. if (!class_exists($className)) return '?????';
  670. $temp = new $className();
  671. if (!method_exists($className, 'getValue')) return '???-???';
  672. $temp->pointerReset();
  673. $ret = "<select {$include} name='{$fname}'>\n";
  674. $ret .= "<option value=''>&nbsp;</option>\n"; // ensures that the user chooses it.
  675. while (FALSE !== ($row = $temp->getValue(0, 'next')))
  676. {
  677. $val = key($row);
  678. $choice = $temp->getValue($val, 'display');
  679. $sel = ($curval == $val) ? " selected='selected' " : '';
  680. $ret .= "<option value='{$val}' {$sel}>{$choice}</option>\n";
  681. }
  682. $ret .= "</select>\n";
  683. return $ret;
  684. case EUF_DB_FIELD : //db_field
  685. $sql = e107::getDb('ue');
  686. $order = ($choices[3]) ? "ORDER BY ".$tp -> toDB($choices[3], true) : "";
  687. if($sql->db_Select($tp -> toDB($choices[0], true), $tp -> toDB($choices[1], true).",".$tp -> toDB($choices[2], true), "1 $order")){
  688. $choiceList = $sql->db_getList('ALL',FALSE);
  689. $ret = "<select {$include} name='{$fname}' >\n";
  690. $ret .= "<option value=''>&nbsp;</option>\n"; // ensures that the user chose it.
  691. foreach($choiceList as $cArray)
  692. {
  693. $cID = trim($cArray[$choices[1]]);
  694. $cText = trim($cArray[$choices[2]]);
  695. $sel = ($curval == $cID) ? " selected='selected' " : "";
  696. $ret .= "<option value='{$cID}' {$sel}>{$cText}</option>\n";
  697. }
  698. $ret .= "</select>\n";
  699. return $ret;
  700. } else {
  701. return "";
  702. }
  703. break;
  704. case EUF_TEXTAREA : //textarea
  705. return "<textarea {$include} name='{$fname}' >{$curval}</textarea>";
  706. break;
  707. case EUF_DATE : //date
  708. if($curval == '0000-00-00') // Quick datepicker fix.
  709. {
  710. $curval = '';
  711. }
  712. return e107::getForm()->datepicker($fname,$curval,'format=yyyy-mm-dd');
  713. break;
  714. case EUF_LANGUAGE : // language
  715. require_once(e_HANDLER."file_class.php");
  716. $fl = new e_file;
  717. $lanlist = $fl->get_dirs(e_LANGUAGEDIR);
  718. sort($lanlist);
  719. $ret = "<select {$include} name='{$fname}'>\n";
  720. $ret .= "<option value=''>&nbsp;</option>\n"; // ensures that the user chose it.
  721. foreach($lanlist as $choice)
  722. {
  723. $choice = trim($choice);
  724. $sel = ($curval == $choice || (!USER && $choice == e_LANGUAGE))? " selected='selected' " : "";
  725. $ret .= "<option value='{$choice}' {$sel}>{$choice}</option>\n";
  726. }
  727. $ret .= "</select>\n";
  728. break;
  729. }
  730. return $ret;
  731. }
  732. // Alias of getStructure();
  733. function getStructure($orderby="user_extended_struct_order")
  734. {
  735. return $this->user_extended_getStruct($orderby);
  736. }
  737. /**
  738. * Preferred version of user_extended_getStruct();
  739. */
  740. function user_extended_getStruct($orderby="user_extended_struct_order")
  741. {
  742. if($ueStruct = getcachedvars('ue_struct'))
  743. {
  744. return $ueStruct;
  745. }
  746. $tp = e107::getParser();
  747. $sql_ue = e107::getDb('ue'); // new db; // Use our own db to avoid interference with other objects
  748. $ret = array();
  749. $parms = "";
  750. if($orderby != "")
  751. {
  752. $parms = "1 ORDER BY ".$tp -> toDB($orderby, true);
  753. }
  754. if($sql_ue->select('user_extended_struct','*',$parms))
  755. {
  756. while($row = $sql_ue->fetch())
  757. {
  758. $ret['user_'.$row['user_extended_struct_name']] = $row;
  759. }
  760. }
  761. cachevars('ue_struct',$ret);
  762. return $ret;
  763. }
  764. function parse_extended_xml($contents, $no_cache = FALSE)
  765. {
  766. if($no_cache == FALSE && $this->extended_xml)
  767. {
  768. return $this->extended_xml;
  769. }
  770. $xml = e107::getXml();
  771. $data = $xml->loadXMLfile(e_CORE."xml/user_extended.xml", true);
  772. $ret['version'] = $data['@attributes']['version'];
  773. unset($info);
  774. foreach($data['item'] as $item)
  775. {
  776. if(is_array($item['include_text']) && !count($item['include_text']))
  777. {
  778. $item['include_text'] = '';
  779. }
  780. $info = array(
  781. "name" => $item['@attributes']['name'],
  782. "text" => "UE_LAN_".strtoupper($item['@attributes']['name']),
  783. "type" => $item['type'],
  784. "values" => $item['values'],
  785. "default" => $item['default'],
  786. "required" => $item['required'],
  787. "read" => $item['read'],
  788. "write" => $item['write'],
  789. "applicable" => $item['applicable'],
  790. "include_text" => $item['include_text'],
  791. "parms" => $item['include_text'],
  792. "regex" => $item['regex']
  793. );
  794. if(is_array($item['default']) && $item['default'] == '')
  795. {
  796. $info['default'] = 0;
  797. }
  798. if($item['regex'])
  799. {
  800. $info['parms'] .= $item['include_text']."^,^".$item['regex']."^,^LAN_UE_FAIL_".strtoupper($item['@attributes']['name']);
  801. }
  802. $ret[$item['@attributes']['name']] = $info;
  803. }
  804. $this->extended_xml = $ret;
  805. return $this->extended_xml;
  806. }
  807. /**
  808. * Proxy Method to retrieve the value of an extended field
  809. * @param int $uid
  810. * @param var $field_name
  811. * @param object $ifnotset [optional]
  812. * @return mixed
  813. */
  814. function get($uid, $field_name, $ifnotset=false)
  815. {
  816. return user_extended_getvalue($uid, $field_name, $ifnotset);
  817. }
  818. /**
  819. * Proxy method for setting the value of an extended field
  820. * (inserts or updates)
  821. *
  822. * @param integer $uid
  823. * @param string $field_name eg. location
  824. * @param string $newvalue eg. USA
  825. * @param string $fieldType [optional] default 'todb' |
  826. * @return boolean;
  827. */
  828. function set($uid, $field_name, $newvalue, $fieldType = 'todb')
  829. {
  830. return $this->user_extended_setvalue($uid, $field_name, $newvalue, $fieldType);
  831. }
  832. /**
  833. * Set the value of an extended field
  834. *
  835. * $ue = new e107_user_extended;
  836. * $result = $ue->user_extended_setvalue(1, 'location', 'Pittsburgh');
  837. *
  838. *
  839. */
  840. function user_extended_setvalue($uid, $field_name, $newvalue, $fieldType = 'todb')
  841. {
  842. $sql = e107::getDb();
  843. $tp = e107::getParser();
  844. $uid = (int)$uid;
  845. switch($fieldType)
  846. {
  847. case 'int':
  848. $newvalue = (int)$newvalue;
  849. break;
  850. case 'escape':
  851. $newvalue = "'".mysql_real_escape_string($newvalue)."'";
  852. break;
  853. default:
  854. $newvalue = "'".$tp->toDB($newvalue)."'";
  855. break;
  856. }
  857. if(substr($field_name, 0, 5) != 'user_')
  858. {
  859. $field_name = 'user_'.$field_name;
  860. }
  861. $qry = "
  862. INSERT INTO `#user_extended` (user_extended_id, {$field_name})
  863. VALUES ({$uid}, {$newvalue})
  864. ON DUPLICATE KEY UPDATE {$field_name} = {$newvalue}
  865. ";
  866. return $sql->db_Select_gen($qry);
  867. }
  868. /**
  869. * Retrieve the value of an extended field
  870. *
  871. * $ue = new e107_user_extended;
  872. * $value = $ue->user_extended_getvalue(2, 'location');
  873. *
  874. */
  875. function user_extended_getvalue($uid, $field_name, $ifnotset=false)
  876. {
  877. $uid = intval($uid);
  878. if(substr($field_name, 0, 5) != 'user_')
  879. {
  880. $field_name = 'user_'.$field_name;
  881. }
  882. $uinfo = get_user_data($uid);
  883. if (!isset($uinfo[$field_name])) return $ifnotset;
  884. return $uinfo[$field_name];
  885. }
  886. /**
  887. * Given a predefined list field, returns the display text corresponding to the passed value
  888. *
  889. * @TODO: consider whether to cache the class object
  890. */
  891. function user_extended_display_text($table, $value)
  892. {
  893. $filename = e_CORE.'sql/extended_'.$table.'.php';
  894. if (!is_readable($filename)) return 'No file: '.$filename;
  895. require_once($filename);
  896. $className = 'extended_'.$table;
  897. if (!class_exists($className)) return '?????';
  898. $temp = new $className();
  899. if (!method_exists($className, 'getValue')) return '???-???';
  900. return $temp->getValue($value);
  901. }
  902. }
  903. ?>