From 2ee32fcd9ad11f0ade3cb779af26d15e52dc3c3b Mon Sep 17 00:00:00 2001 From: e107steved Date: Sat, 29 Nov 2008 21:16:54 +0000 Subject: [PATCH] Userclasses - add checks for duplicate names, caching for class tree, some checking for stupid values --- e107_admin/userclass2.php | 157 +++++++------ e107_handlers/userclass_class.php | 208 ++++++++++++------ .../English/admin/lan_userclass2.php | 9 +- 3 files changed, 232 insertions(+), 142 deletions(-) diff --git a/e107_admin/userclass2.php b/e107_admin/userclass2.php index b0826937b..9504811bf 100644 --- a/e107_admin/userclass2.php +++ b/e107_admin/userclass2.php @@ -11,9 +11,9 @@ | GNU General Public License (http://gnu.org). | | $Source: /cvs_backup/e107_0.8/e107_admin/userclass2.php,v $ -| $Revision: 1.15 $ -| $Date: 2008-11-29 17:35:38 $ -| $Author: secretr $ +| $Revision: 1.16 $ +| $Date: 2008-11-29 21:16:48 $ +| $Author: e107steved $ +----------------------------------------------------------------------------+ */ @@ -204,17 +204,17 @@ if (isset($_POST['delete'])) //--------------------------------------------------- // Add/Edit class information //--------------------------------------------------- -if (isset($_POST['updateclass']) || isset($_POST['createclass'])) +if (($action == 'config') && isset($_POST['createclass'])) // Add or edit { - $class_record = array( - 'userclass_name' => varset($tp->toDB($_POST['userclass_name']),''), - 'userclass_description' => varset($tp->toDB($_POST['userclass_description']),''), - 'userclass_editclass' => intval(varset($_POST['userclass_editclass'],0)), - 'userclass_parent' => intval(varset($_POST['userclass_parent'],0)), - 'userclass_visibility' => intval(varset($_POST['userclass_visibility'],0)), - 'userclass_icon' => varset($tp->toDB($_POST['userclass_icon']),''), - 'userclass_type' => intval(varset($_POST['userclass_type'],UC_TYPE_STD)) - ); + $class_record = array( + 'userclass_name' => varset($tp->toDB($_POST['userclass_name']),''), + 'userclass_description' => varset($tp->toDB($_POST['userclass_description']),''), + 'userclass_editclass' => intval(varset($_POST['userclass_editclass'],0)), + 'userclass_parent' => intval(varset($_POST['userclass_parent'],0)), + 'userclass_visibility' => intval(varset($_POST['userclass_visibility'],0)), + 'userclass_icon' => varset($tp->toDB($_POST['userclass_icon']),''), + 'userclass_type' => intval(varset($_POST['userclass_type'],UC_TYPE_STD)) + ); if ($class_record['userclass_type'] == UC_TYPE_GROUP) { $temp = array(); @@ -225,48 +225,64 @@ if (isset($_POST['updateclass']) || isset($_POST['createclass'])) $class_record['userclass_accum'] = implode(',',$temp); } - $do_tree = FALSE; + $do_tree = FALSE; // Set flag to rebuild tree if no errors + $forwardVals = FALSE; // Set to ripple through existing values to a subsequent pass - if (isset($_POST['createclass']) && $_POST['userclass_id']) - { - check_allowed($_POST['userclass_id']); - $class_record['userclass_id'] = intval($_POST['userclass_id']); - $e_userclass->save_edited_class($class_record); - userclass2_adminlog("03","ID:{$class_record['userclass_id']} (".$class_record['userclass_name'].")"); - $do_tree = TRUE; - $message = UCSLAN_5; - } - elseif (isset($_POST['createclass'])) - { - if($class_record['userclass_name']) - { - if (getperms("0") || ($class_record['userclass_editclass'] && check_class($class_record['userclass_editclass']))) - { - $i = 1; - while ($sql->db_Select('userclass_classes', '*', "userclass_id='".$i."' ") && $i < 255) - { - $i++; - } - if ($i < 245) - { - $class_record['userclass_id'] = $i; - $e_userclass->add_new_class($class_record); - userclass2_adminlog("01","ID:{$class_record['userclass_id']} (".$class_record['userclass_name'].")"); - $do_tree = TRUE; - } - $message = UCSLAN_6; - } - else - { - header("location:".SITEURL); - exit; - } + $tempID = intval(varset($_POST['userclass_id'], -1)); + if (($tempID < 0) && $e_userclass->ucGetClassIDFromName($class_record['userclass_name'])) + { // Duplicate name + $message = UCSLAN_63; + $forwardVals = TRUE; } - else + elseif ($e_userclass->checkAdminInfo($class_record, $tempID) === FALSE) { - $message = UCSLAN_37; + $message = UCSLAN_86; + } + + if (!$forwardVals) + { + if ($tempID > 0) + { // Editing existing class here + check_allowed($_POST['userclass_id']); + $class_record['userclass_id'] = $tempID; + $e_userclass->save_edited_class($class_record); + userclass2_adminlog("03","ID:{$class_record['userclass_id']} (".$class_record['userclass_name'].")"); + $do_tree = TRUE; + $message .= UCSLAN_5; + } + else + { // Creating new class + if($class_record['userclass_name']) + { + if (getperms("0") || ($class_record['userclass_editclass'] && check_class($class_record['userclass_editclass']))) + { + $i = $e_userclass->findNewClassID(); + if ($i === FALSE) + { + $message = UCSLAN_85; + } + else + { + $class_record['userclass_id'] = $i; + $e_userclass->add_new_class($class_record); + userclass2_adminlog("01","ID:{$class_record['userclass_id']} (".$class_record['userclass_name'].")"); + $do_tree = TRUE; + $message .= UCSLAN_6; + } + } + else + { + header("location:".SITEURL); + exit; + } + } + else + { + $message = UCSLAN_37; // Class name required + $forwardVals = TRUE; + } + } } - } if ($do_tree) { @@ -298,6 +314,7 @@ switch ($action) { $class_num = intval(varset($uc_qs[2],0)); } + $userclass_id = 0; // Set defaults for new class to start with $userclass_name = ''; $userclass_description = ''; @@ -307,22 +324,25 @@ switch ($action) $userclass_icon = ''; $userclass_type = UC_TYPE_STD; $userclass_groupclass = ''; - if ($params == 'edit') + if ($params == 'edit' || $forwardVals) { - check_allowed($class_num); - $sql->db_Select('userclass_classes', '*', "userclass_id='".intval($class_num)."' "); - $row = $sql->db_Fetch(); - $userclass_id = $row['userclass_id']; // Update fields from DB if editing - $userclass_name = $row['userclass_name']; - $userclass_description = $row['userclass_description']; - $userclass_editclass = $row['userclass_editclass']; - $userclass_visibility = $row['userclass_visibility']; - $userclass_parent = $row['userclass_parent']; - $userclass_icon = $row['userclass_icon']; - $userclass_type = $row['userclass_type']; + if (!$forwardVals) + { // Get the values from DB (else just recycle data uer was trying to store) + check_allowed($class_num); + $sql->db_Select('userclass_classes', '*', "userclass_id='".intval($class_num)."' "); + $class_record = $sql->db_Fetch(); + $userclass_id = $class_record['userclass_id']; // Update fields from DB if editing + } + $userclass_name = $class_record['userclass_name']; + $userclass_description = $class_record['userclass_description']; + $userclass_editclass = $class_record['userclass_editclass']; + $userclass_visibility = $class_record['userclass_visibility']; + $userclass_parent = $class_record['userclass_parent']; + $userclass_icon = $class_record['userclass_icon']; + $userclass_type = $class_record['userclass_type']; if ($userclass_type == UC_TYPE_GROUP) { - $userclass_groupclass = $row['userclass_accum']; + $userclass_groupclass = $class_record['userclass_accum']; } } @@ -593,19 +613,12 @@ $ns->tablerender(UCSLAN_21, $text); if (isset($_POST['add_class_tree'])) { // Create a default tree - $message = UCSLAN_62; - if (!$e_userclass->update_db(TRUE)) - { - $message .= UCSLAN_63; - } - else - { + $message = UCSLAN_62; $e_userclass->set_default_structure(); $e_userclass->calc_tree(); $e_userclass->save_tree(); $e_userclass->read_tree(TRUE); // Need to re-read the tree to show correct info $message .= UCSLAN_64; - } } if (isset($_POST['flatten_class_tree'])) diff --git a/e107_handlers/userclass_class.php b/e107_handlers/userclass_class.php index a94fc0874..cfe8ad55c 100644 --- a/e107_handlers/userclass_class.php +++ b/e107_handlers/userclass_class.php @@ -11,9 +11,9 @@ | GNU General Public License (http://gnu.org). | | $Source: /cvs_backup/e107_0.8/e107_handlers/userclass_class.php,v $ -| $Revision: 1.20 $ -| $Date: 2008-11-29 17:35:38 $ -| $Author: secretr $ +| $Revision: 1.21 $ +| $Date: 2008-11-29 21:16:48 $ +| $Author: e107steved $ +----------------------------------------------------------------------------+ */ @@ -24,6 +24,8 @@ This class handles everything a user needs. Admin functions inherit from it. if (!defined('e107_INIT')) { exit; } +require_once(e_HANDLER.'arraystorage_class.php'); + include_lan(e_LANGUAGEDIR.e_LANGUAGE."/lan_userclass.php"); @@ -41,6 +43,7 @@ define("e_UC_NOBODY", 255); define("e_UC_ADMINMOD",249); define("e_UC_MODS",248); //define("e_UC_USERS",247); +define('e_UC_SPECIAL_BASE',245); // Assign class IDs 245 and above for fixed/special purposes define('UC_CLASS_ICON_DIR','userclasses/'); // Directory for userclass icons define('UC_ICON_DIR',e_IMAGE.'generic/'); // Directory for the icons used in the admin tree displays @@ -49,6 +52,8 @@ define('e_UC_BLANK','-1'); define('UC_TYPE_STD', '0'); define('UC_TYPE_GROUP', '1'); +define('UC_CACHE_TAG', 'nomd5_classtree'); + class user_class { var $class_tree; // Simple array, filled with current tree. Additional field class_children is an array of child user classes (by ID) @@ -78,7 +83,7 @@ class user_class $this->text_class_link = array('public' => e_UC_PUBLIC, 'guest' => e_UC_GUEST, 'nobody' => e_UC_NOBODY, 'member' => e_UC_MEMBER, 'admin' => e_UC_ADMIN, 'main' => e_UC_MAINADMIN, 'readonly' => e_UC_READONLY); - $this->read_tree(TRUE); // Initialise the classes on entry + $this->readTree(TRUE); // Initialise the classes on entry } @@ -86,59 +91,73 @@ class user_class Ensure the tree of userclass data is stored in our object. Only read if its either not present, or the $force flag is set */ - function read_tree($force = FALSE) + function readTree($force = FALSE) { - if (isset($this->class_tree) && !$force) return $this->class_tree; + if (isset($this->class_tree) && count($this->class_tree) && !$force) return $this->class_tree; + + global $e107; $this->class_tree = array(); $this->class_parents = array(); - $this->sql_r->db_Select("userclass_classes", '*', "ORDER BY userclass_parent", 'nowhere'); // The order statement should give a consistent return - - while ($row = $this->sql_r->db_Fetch(MYSQL_ASSOC)) + $array = new ArrayData; + if ($temp = $e107->ecache->retrieve_sys(UC_CACHE_TAG)) { - $this->class_tree[$row['userclass_id']] = $row; - $this->class_tree[$row['userclass_id']]['class_children'] = array(); // Create the child array in case needed + $this->class_tree = $array->ReadArray($temp); + unset($temp); } - - // Add in any fixed classes that aren't already defined - foreach ($this->fixed_classes as $c => $d) + else { - if (!isset($this->class_tree[$c]) && ($c != e_UC_PUBLIC)) - { -// $this->class_tree[$c]['userclass_parent'] = (($c == e_UC_MEMBER) || ($c == e_UC_NOBODY)) ? e_UC_PUBLIC : e_UC_MEMBER; - $this->class_tree[$c]['userclass_parent'] = (($c == e_UC_ADMIN) || ($c == e_UC_MAINADMIN)) ? e_UC_MEMBER : e_UC_PUBLIC ; - $this->class_tree[$c]['userclass_id'] = $c; - $this->class_tree[$c]['userclass_name'] = $d; - $this->class_tree[$c]['userclass_description'] = 'Fixed class'; - $this->class_tree[$c]['userclass_visibility'] = e_UC_PUBLIC; - $this->class_tree[$c]['userclass_editclass'] = e_UC_MAINADMIN; - $this->class_tree[$c]['userclass_accum'] = $c; - $this->class_tree[$c]['userclass_type'] = UC_TYPE_STD; - } + $this->sql_r->db_Select("userclass_classes", '*', "ORDER BY userclass_parent", 'nowhere'); // The order statement should give a consistent return + + while ($row = $this->sql_r->db_Fetch(MYSQL_ASSOC)) + { + $this->class_tree[$row['userclass_id']] = $row; + $this->class_tree[$row['userclass_id']]['class_children'] = array(); // Create the child array in case needed + } + + + // Add in any fixed classes that aren't already defined + foreach ($this->fixed_classes as $c => $d) + { + if (!isset($this->class_tree[$c]) && ($c != e_UC_PUBLIC)) + { + // $this->class_tree[$c]['userclass_parent'] = (($c == e_UC_MEMBER) || ($c == e_UC_NOBODY)) ? e_UC_PUBLIC : e_UC_MEMBER; + $this->class_tree[$c]['userclass_parent'] = (($c == e_UC_ADMIN) || ($c == e_UC_MAINADMIN)) ? e_UC_MEMBER : e_UC_PUBLIC ; + $this->class_tree[$c]['userclass_id'] = $c; + $this->class_tree[$c]['userclass_name'] = $d; + $this->class_tree[$c]['userclass_description'] = 'Fixed class'; + $this->class_tree[$c]['userclass_visibility'] = e_UC_PUBLIC; + $this->class_tree[$c]['userclass_editclass'] = e_UC_MAINADMIN; + $this->class_tree[$c]['userclass_accum'] = $c; + $this->class_tree[$c]['userclass_type'] = UC_TYPE_STD; + } + } + + $userCache = $array->WriteArray($this->class_tree, FALSE); + $e107->ecache->set_sys(UC_CACHE_TAG,$userCache); + unset($userCache); } // Now build the tree foreach ($this->class_tree as $uc) { - if ($uc['userclass_parent'] == e_UC_PUBLIC) -// if (($uc['userclass_parent'] == e_UC_PUBLIC) || ($uc['userclass_parent'] == e_UC_NOBODY) || ($uc['userclass_parent'] == e_UC_MEMBER)) - { // Note parent (top level) classes - $this->class_parents[$uc['userclass_id']] = $uc['userclass_id']; - } - else - { - if (!array_key_exists($uc['userclass_parent'],$this->class_tree)) - { - echo "Orphaned class record: ID=".$uc['userclass_id']." Name=".$uc['userclass_name']." Parent=".$uc['userclass_parent']."
"; + if ($uc['userclass_parent'] == e_UC_PUBLIC) + { // Note parent (top level) classes + $this->class_parents[$uc['userclass_id']] = $uc['userclass_id']; } else - { // Add to array - $this->class_tree[$uc['userclass_parent']]['class_children'][] = $uc['userclass_id']; + { + if (!array_key_exists($uc['userclass_parent'],$this->class_tree)) + { + echo "Orphaned class record: ID=".$uc['userclass_id']." Name=".$uc['userclass_name']." Parent=".$uc['userclass_parent']."
"; + } + else + { // Add to array + $this->class_tree[$uc['userclass_parent']]['class_children'][] = $uc['userclass_id']; + } } - } } - } @@ -514,7 +533,7 @@ class user_class function uc_get_classlist($filter = FALSE) { $ret = array(); - $this->read_tree(FALSE); // Make sure we have data + $this->readTree(FALSE); // Make sure we have data foreach ($this->class_tree as $k => $v) { if (!$filter || check_class($filter)) @@ -562,6 +581,20 @@ class user_class return ''; } + function ucGetClassIDFromName($name) + { + $this->readTree(); + // We have all the info - can just search the array + foreach ($this->class_tree as $uc => $info) + { + if ($info['userclass_name'] == $name) + { + return $uc; + } + } + return FALSE; // not found + } + /* Return all users in a particular class or set of classes. @@ -740,7 +773,7 @@ class user_class_admin extends user_class function calc_tree() { // echo "Calc Tree
"; - $this->read_tree(TRUE); // Make sure we have accurate data + $this->readTree(TRUE); // Make sure we have accurate data foreach ($this->class_parents as $cp) { $rights = array(); @@ -966,12 +999,38 @@ class user_class_admin extends user_class } return $ret; } - + + + // Return an unused class ID - FALSE if none spare. Misses the predefined classes. + function findNewClassID() + { + $i = 1; + // Start by allocating a new class with a number higher than any previously allocated + foreach ($this->class_tree as $id => $r) + { + if ($id < e_UC_SPECIAL_BASE) + { + $i = max($i,$id); + } + } + $i++; + if ($i < e_UC_SPECIAL_BASE) return $i; + + // Looks like we've had a lot of activity in classes - try and find a gap. + for ($i = 1; ($i < e_UC_SPECIAL_BASE); $i++) + { + if (!isset($this->class_tree[$i])) return $i; + } + return FALSE; // Just in case all classes assigned! + } + + function add_new_class($classrec) { // echo "Add new class
"; $this->sql_r->db_Insert('userclass_classes',$this->copy_rec($classrec, TRUE)); + $this->clearCache(); } @@ -994,6 +1053,7 @@ class user_class_admin extends user_class } } $this->sql_r->db_Update('userclass_classes', $qry." WHERE `userclass_id`='{$classrec['userclass_id']}'"); + $this->clearCache(); } @@ -1008,35 +1068,45 @@ class user_class_admin extends user_class if ($c['userclass_visibility'] == $class_id) return FALSE; } if (!$this->sql_r->db_Delete('userclass_classes', "`userclass_id`='{$class_id}'")) return FALSE; - $this->read_tree(TRUE); // Re-read the class tree + $this->clearCache(); + $this->readTree(TRUE); // Re-read the class tree return TRUE; } - - - // Update the userclass table with the extra fields for 0.8 - // Return TRUE if all fields present. Return FALSE if update needed - function update_db($check_only = FALSE) - { // Just run through all the fields that should be there, and add if not - - $fn = 1; // Count fields - $prev_field = 'userclass_id'; - foreach ($this->field_list as $fl => $parms) + // Certain fields on admin records have constraints on their values. + // Checks the passed array, and updates any values which are unacceptable. + // Returns TRUE if nothing changed, FALSE if changes made + function checkAdminInfo(&$data, $id) { - $field_name = $this->sql_r->db_Field("userclass_classes",$fn); -// echo "Compare: {$field_name} : {$fl}
"; - if ($field_name != $fl) - { - if ($check_only) return FALSE; - $this->sql_r->db_Select_gen("ALTER TABLE #userclass_classes ADD `{$fl}` {$parms} AFTER `{$prev_field}`;"); - } - $fn++; - $prev_field = $fl; + $ret = TRUE; + if ($id < e_UC_SPECIAL_BASE) return TRUE; + if (isset($data['userclass_parent'])) + { + if ($data['userclass_parent'] < e_UC_SPECIAL_BASE) + { + $data['userclass_parent'] = e_UC_NOBODY; + $ret = FALSE; + } + } + if (isset($data['userclass_editclass'])) + { + if ($id == e_UC_MAINADMIN) + { + if ($data['userclass_editclass'] < e_UC_MAINADMIN) + { + $data['userclass_editclass'] = e_UC_MAINADMIN; + $ret = FALSE; + } + } + elseif ($data['userclass_editclass'] < e_UC_SPECIAL_BASE) + { + $data['userclass_editclass'] = e_UC_MAINADMIN; + $ret = FALSE; + } + } + return $ret; } - return TRUE; - } - // Set default tree structure @@ -1088,6 +1158,12 @@ class user_class_admin extends user_class } } } + + function clearCache() + { + global $e107; + $e107->ecache->clear_sys(UC_CACHE_TAG); + } } diff --git a/e107_languages/English/admin/lan_userclass2.php b/e107_languages/English/admin/lan_userclass2.php index 6d9898b35..04f310667 100644 --- a/e107_languages/English/admin/lan_userclass2.php +++ b/e107_languages/English/admin/lan_userclass2.php @@ -4,8 +4,8 @@ | e107 website system - Language File. | | $Source: /cvs_backup/e107_0.8/e107_languages/English/admin/lan_userclass2.php,v $ -| $Revision: 1.5 $ -| $Date: 2008-11-27 22:07:36 $ +| $Revision: 1.6 $ +| $Date: 2008-11-29 21:16:54 $ | $Author: e107steved $ +----------------------------------------------------------------------------+ */ @@ -71,7 +71,7 @@ define("UCSLAN_59", 'Enable admin logging of user class edits'); define("UCSLAN_60", 'User Class Configuration options'); define("UCSLAN_61", 'User class setup'); define("UCSLAN_62", 'Create default class tree: '); -define("UCSLAN_63", 'Must add new DB fields first'); +define("UCSLAN_63", 'That class name already exists - please choose another'); define("UCSLAN_64", 'completed'); define("UCSLAN_65", 'Flatten user class hierarchy: '); define("UCSLAN_66", 'Confirm flatten user class hierarchy'); @@ -93,7 +93,8 @@ define('UCSLAN_81', 'Group'); define('UCSLAN_82', 'A group brings together a number of individual classes'); define('UCSLAN_83', 'Classes in group'); define('UCSLAN_84', ' (Group)'); -define('UCSLAN_85', ''); +define('UCSLAN_85', 'You have assigned all available classes; please reassign one which is not in use'); +define('UCSLAN_86', 'Some settings not allowed for admin classes - they have been set to defaults. '); define("UCSLAN_UPDATE", 'Update');