From 8b40272996c522aba07755a65f651c01d58c3978 Mon Sep 17 00:00:00 2001 From: paul Date: Fri, 1 Sep 2006 09:27:29 +0000 Subject: [PATCH] Pulled out SQL statements into separate lines to allow for easier debugability, fixed up the documentation, prettied up the code to Campware coding conventions. --- livesupport/src/modules/alib/var/subj.php | 643 +++++++++++++--------- 1 file changed, 385 insertions(+), 258 deletions(-) diff --git a/livesupport/src/modules/alib/var/subj.php b/livesupport/src/modules/alib/var/subj.php index 19d6481f3..c18e88310 100644 --- a/livesupport/src/modules/alib/var/subj.php +++ b/livesupport/src/modules/alib/var/subj.php @@ -2,26 +2,26 @@ /*------------------------------------------------------------------------------ Copyright (c) 2004 Media Development Loan Fund - + This file is part of the LiveSupport project. http://livesupport.campware.org/ To report bugs, send an e-mail to bugs@campware.org - + LiveSupport is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. - + LiveSupport is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - + You should have received a copy of the GNU General Public License along with LiveSupport; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA - - + + Author : $Author$ Version : $Revision$ Location : $URL$ @@ -32,439 +32,557 @@ define('ALIBERR_NOTGR', 20); define('ALIBERR_BADSMEMB', 21); /** - * Subj class + * Subj class * - * users + groups - * with "linearized recursive membership" ;) + * users + groups + * with "linearized recursive membership" ;) * (allow adding users to groups or groups to groups) - * - * @author $Author$ - * @version $Revision$ - * @see ObjClasses - * @see Alib + * + * @author $Author$ + * @version $Revision$ + * @see ObjClasses + * @see Alib */ -class Subjects extends ObjClasses{ +class Subjects extends ObjClasses { var $subjTable; var $smembTable; + /** - * Constructor + * Constructor * - * @param dbc object - * @param config array - * @return this + * @param object $dbc + * @param array $config + * @return this */ function Subjects(&$dbc, $config) { parent::ObjClasses($dbc, $config); $this->subjTable = $config['tblNamePrefix'].'subjs'; $this->smembTable = $config['tblNamePrefix'].'smemb'; - } + } // constructor + /* ======================================================= public methods */ /** - * Add new subject + * Add new subject * - * @param login string - * @param pass string, optional - * @param realname string, optional - * @param passenc boolean, optional, password already encrypted if true - * @return int/err + * @param string $login + * @param string $pass, optional + * @param string $realname, optional + * @param boolean $passenc, optional, password already encrypted if true + * @return int/err */ function addSubj($login, $pass=NULL, $realname='', $passenc=FALSE) { - if(!$login) return $this->dbc->raiseError( - get_class($this)."::addSubj: empty login" - ); + if(!$login) { + return $this->dbc->raiseError(get_class($this)."::addSubj: empty login"); + } $id = $this->dbc->nextId("{$this->subjTable}_id_seq"); - if(PEAR::isError($id)) return $id; - if(!is_null($pass) && !$passenc) $pass = md5($pass); - $r = $this->dbc->query(" - INSERT INTO {$this->subjTable} (id, login, pass, type, realname) + if (PEAR::isError($id)) { + return $id; + } + if (!is_null($pass) && !$passenc) { + $pass = md5($pass); + } + $sql = "INSERT INTO {$this->subjTable} (id, login, pass, type, realname) VALUES ($id, '$login', ". (is_null($pass) ? "'!', 'G'" : "'$pass', 'U'").", - '$realname') - "); - if(PEAR::isError($r)) return $r; + '$realname')"; + $r = $this->dbc->query($sql); + if (PEAR::isError($r)) { + return $r; + } return $id; - } + } // fn addSubj + /** - * Remove subject by uid or by login + * Remove subject by uid or by login * - * @param login string - * @param uid int, optional, default: null - * @return boolean/err + * @param string $login + * @param int $uid, optional, default: null + * @return boolean/err */ function removeSubj($login, $uid=NULL) { - if(is_null($uid)) $uid = $this->getSubjId($login); - if(PEAR::isError($uid)) return $uid; - $r = $this->dbc->query("DELETE FROM {$this->smembTable} - WHERE (uid='$uid' OR gid='$uid') AND mid is null"); - if(PEAR::isError($r)) return $r; - $r = $this->dbc->query("DELETE FROM {$this->subjTable} - WHERE login='$login'"); - if(PEAR::isError($r)) return $r; + if (is_null($uid)) { + $uid = $this->getSubjId($login); + } + if (PEAR::isError($uid)) { + return $uid; + } + $sql = "DELETE FROM {$this->smembTable} + WHERE (uid='$uid' OR gid='$uid') AND mid is null"; + $r = $this->dbc->query($sql); + if (PEAR::isError($r)) { + return $r; + } + $sql2 = "DELETE FROM {$this->subjTable} + WHERE login='$login'"; + $r = $this->dbc->query($sql2); + if (PEAR::isError($r)) { + return $r; + } return $this->_rebuildRels(); - } + } // fn removeSubj + /** - * Check login and password + * Check login and password * - * @param login string - * @param pass string, optional - * @return boolean/int/err + * @param string $login + * @param string $pass, optional + * @return boolean/int/err */ function authenticate($login, $pass='') { $cpass = md5($pass); - $id = $this->dbc->getOne(" - SELECT id FROM {$this->subjTable} - WHERE login='$login' AND pass='$cpass' AND type='U' - "); - if(PEAR::isError($id)) return $id; + $sql = "SELECT id FROM {$this->subjTable} + WHERE login='$login' AND pass='$cpass' AND type='U'"; + $id = $this->dbc->getOne($sql); + if (PEAR::isError($id)) { + return $id; + } return (is_null($id) ? FALSE : $id); - } + } // fn authenticate + /** - * Set lastlogin or lastfail timestamp + * Set lastlogin or lastfail timestamp * - * @param login string - * @param failed boolean, true=> set lastfail, false=> set lastlogin - * @return boolean/int/err + * @param string $login + * @param boolean $failed, true=> set lastfail, false=> set lastlogin + * @return boolean/int/err */ function setTimeStamp($login, $failed=FALSE) { $fld = ($failed ? 'lastfail' : 'lastlogin'); - $r = $this->dbc->query(" - UPDATE {$this->subjTable} SET $fld=now() - WHERE login='$login' - "); - if(PEAR::isError($r)) return $r; + $sql = "UPDATE {$this->subjTable} SET $fld=now() + WHERE login='$login'"; + $r = $this->dbc->query($sql); + if (PEAR::isError($r)) { + return $r; + } return TRUE; - } + } // fn setTimeStamp + /** - * Change user password + * Change user password * - * @param login string - * @param oldpass string, old password (optional for 'superuser mode') - * @param pass string, optional - * @param passenc boolean, optional, password already encrypted if true - * @return boolean/err + * @param string $login + * @param string $oldpass, old password (optional for 'superuser mode') + * @param string $pass, optional + * @param boolean $passenc, optional, password already encrypted if true + * @return boolean/err */ function passwd($login, $oldpass=null, $pass='', $passenc=FALSE) { - if(!$passenc) $cpass = md5($pass); - else $cpass = $pass; - if(!is_null($oldpass)){ + if (!$passenc) { + $cpass = md5($pass); + } else { + $cpass = $pass; + } + if (!is_null($oldpass)) { $oldcpass = md5($oldpass); $oldpCond = "AND pass='$oldcpass'"; - }else{ $oldpCond = ''; } - $r = $this->dbc->query(" - UPDATE {$this->subjTable} SET pass='$cpass' - WHERE login='$login' $oldpCond AND type='U' - "); - if(PEAR::isError($r)) return $r; + } else { + $oldpCond = ''; + } + $sql = "UPDATE {$this->subjTable} SET pass='$cpass' + WHERE login='$login' $oldpCond AND type='U'"; + $r = $this->dbc->query($sql); + if (PEAR::isError($r)) { + return $r; + } return TRUE; - } + } // fn passwd + /* --------------------------------------------------------------- groups */ - + /** - * Add {login} and direct/indirect members to {gname} and to groups, - * where {gname} is [in]direct member + * Add {login} and direct/indirect members to {gname} and to groups, + * where {gname} is [in]direct member * - * @param login string - * @param gname string - * @return int/err + * @param string $login + * @param string $gname + * @return int/err */ function addSubj2Gr($login, $gname) { - $uid = $this->getSubjId($login); if(PEAR::isError($uid)) return $uid; - $gid = $this->getSubjId($gname); if(PEAR::isError($gid)) return $gid; - $isgr = $this->isGroup($gid); if(PEAR::isError($isgr)) return $isgr; - if(!$isgr) return PEAR::raiseError( - "Subjects::addSubj2Gr: Not a group ($gname)", ALIBERR_NOTGR - ); + $uid = $this->getSubjId($login); + if (PEAR::isError($uid)) { + return $uid; + } + $gid = $this->getSubjId($gname); + if (PEAR::isError($gid)) { + return $gid; + } + $isgr = $this->isGroup($gid); + if (PEAR::isError($isgr)) { + return $isgr; + } + if (!$isgr) { + return PEAR::raiseError("Subjects::addSubj2Gr: Not a group ($gname)", ALIBERR_NOTGR); + } // add subject and all [in]direct members to group $gname: $mid = $this->_plainAddSubj2Gr($uid, $gid); - if(PEAR::isError($mid)) return $mid; + if (PEAR::isError($mid)) { + return $mid; + } // add it to all groups where $gname is [in]direct member: - $marr = $this->_listRMemb($gid); if(PEAR::isError($marr)) return $marr; + $marr = $this->_listRMemb($gid); + if (PEAR::isError($marr)) { + return $marr; + } foreach($marr as $k=>$v){ $r = $this->_plainAddSubj2Gr( $uid, $v['gid'], intval($v['level'])+1, $v['id']); - if(PEAR::isError($r)) return $r; + if (PEAR::isError($r)) { + return $r; + } } return $mid; - } + } // fn addSubj2Gr + /** - * Remove subject from group + * Remove subject from group * - * @param login string - * @param gname string - * @return boolean/err + * @param string $login + * @param string $gname + * @return boolean/err */ function removeSubjFromGr($login, $gname) { - $uid = $this->getSubjId($login); if(PEAR::isError($uid)) return $uid; - $gid = $this->getSubjId($gname); if(PEAR::isError($gid)) return $gid; - $mid = $this->dbc->getOne($q = "SELECT id FROM {$this->smembTable} - WHERE uid='$uid' AND gid='$gid' AND mid is null"); - if(is_null($mid)) return FALSE; - if(PEAR::isError($mid)) return $mid; + $uid = $this->getSubjId($login); + if (PEAR::isError($uid)) { + return $uid; + } + $gid = $this->getSubjId($gname); + if (PEAR::isError($gid)) { + return $gid; + } + $sql = "SELECT id FROM {$this->smembTable} + WHERE uid='$uid' AND gid='$gid' AND mid is null"; + $mid = $this->dbc->getOne($sql); + if (is_null($mid)) { + return FALSE; + } + if (PEAR::isError($mid)) { + return $mid; + } // remove it: - $r = $this->_removeMemb($mid); if(PEAR::isError($r)) return $r; - // and rebuild indirect memberships: - $r = $this->_rebuildRels(); if(PEAR::isError($r)) return $r; + $r = $this->_removeMemb($mid); + if (PEAR::isError($r)) { + return $r; + } + // and rebuild indirect memberships: + $r = $this->_rebuildRels(); + if (PEAR::isError($r)) { + return $r; + } return TRUE; - } - + } // fn removeSubjFromGr + + /* --------------------------------------------------------- info methods */ /** - * Get subject id from login + * Get subject id from login * - * @param login string - * @return int/err + * @param string $login + * @return int/err */ function getSubjId($login) { - return $this->dbc->getOne("SELECT id FROM {$this->subjTable} - WHERE login='$login'"); - } + $sql = "SELECT id FROM {$this->subjTable} + WHERE login='$login'"; + return $this->dbc->getOne($sql); + } // fn getSubjId + /** - * Get subject name (login) from id + * Get subject name (login) from id * - * @param id int - * @param fld string - * @return string/err + * @param int $id + * @param string $fld + * @return string/err */ function getSubjName($id, $fld='login') { - return $this->dbc->getOne("SELECT $fld FROM {$this->subjTable} - WHERE id='$id'"); - } + $sql = "SELECT $fld FROM {$this->subjTable} + WHERE id='$id'"; + return $this->dbc->getOne($sql); + } // fn getSubjName + /** - * Get all subjects + * Get all subjects * - * @param flds string, optional - * @return array/err + * @param string $flds, optional + * @return array/err */ function getSubjects($flds='id, login') { - return $this->dbc->getAll("SELECT $flds FROM {$this->subjTable}"); - } + $sql = "SELECT $flds FROM {$this->subjTable}"; + return $this->dbc->getAll($sql); + } // fn getSubjects + /** - * Get subjects with count of direct members + * Get subjects with count of direct members * - * @return array/err + * @return array/err */ function getSubjectsWCnt() { - return $this->dbc->getAll(" + $sql = " SELECT count(m.uid)as cnt, s.id, s.login, s.type FROM {$this->subjTable} s LEFT JOIN {$this->smembTable} m ON m.gid=s.id WHERE m.mid is null GROUP BY s.id, s.login, s.type - ORDER BY s.id" - ); - } - + ORDER BY s.id"; + return $this->dbc->getAll($sql); + } // fn getSubjectsWCnt + + /** - * Return true if subject is a group + * Return true if subject is a group * - * @param gid int - * @return boolean/err + * @param int $gid + * @return boolean/err */ function isGroup($gid) { - $r = $this->dbc->getOne("SELECT type FROM {$this->subjTable} - WHERE id='$gid'"); - if(PEAR::isError($r)) return $r; - return ($r === 'G' ); - } - + $sql = "SELECT type FROM {$this->subjTable} + WHERE id='$gid'"; + $r = $this->dbc->getOne($sql); + if (PEAR::isError($r)) { + return $r; + } + return ($r === 'G'); + } // fn isGroup + + /** - * List direct members of group + * List direct members of group * - * @param gid int - * @return array/err + * @param int $gid + * @return array/err */ function listGroup($gid) { - return $this->dbc->getAll("SELECT s.id, s.login, s.type + $sql = "SELECT s.id, s.login, s.type FROM {$this->smembTable} m, {$this->subjTable} s - WHERE m.uid=s.id AND m.mid is null AND m.gid='$gid'"); - } + WHERE m.uid=s.id AND m.mid is null AND m.gid='$gid'"; + return $this->dbc->getAll($sql); + } // fn listGroup + /** - * Return true if uid is [id]direct member of gid + * Return true if uid is [id]direct member of gid * - * @param uid int, local user id - * @param gid int, local group id - * @return boolean + * @param int $uid, local user id + * @param int $gid, local group id + * @return boolean */ function isMemberOf($uid, $gid) { - $res = $this->dbc->getOne(" + $sql = " SELECT count(*)as cnt FROM {$this->smembTable} WHERE uid='$uid' AND gid='$gid' - "); - if(PEAR::isError($res)) return $res; + "; + $res = $this->dbc->getOne($sql); + if (PEAR::isError($res)) { + return $res; + } return (intval($res) > 0); - } + } // fn isMemberOf + /* ==================================================== "private" methods */ - + /** - * Create membership record + * Create membership record * - * @param uid int - * @param gid int - * @param level int, optional - * @param mid int, optional - * @return int/err + * @param int $uid + * @param int $gid + * @param int $level, optional + * @param int $mid, optional + * @return int/err */ function _addMemb($uid, $gid, $level=0, $mid='null') { - if($uid == $gid) return PEAR::raiseError( - "Subjects::_addMemb: uid==gid ($uid)", ALIBERR_BADSMEMB - ); - $a = $this->dbc->getAll("SELECT id, level, mid FROM {$this->smembTable} - WHERE uid='$uid' AND gid='$gid' ORDER BY level ASC"); - if(PEAR::isError($a)) return $a; - if(count($a)>0){ + if($uid == $gid) { + return PEAR::raiseError("Subjects::_addMemb: uid==gid ($uid)", ALIBERR_BADSMEMB); + } + $sql = "SELECT id, level, mid FROM {$this->smembTable} + WHERE uid='$uid' AND gid='$gid' ORDER BY level ASC"; + $a = $this->dbc->getAll($sql); + if (PEAR::isError($a)) { + return $a; + } + if (count($a) > 0) { $a0 = $a[0]; $id = $a0['id']; - if($level < intval($a0['level'])){ - $r = $this->dbc->query("UPDATE {$this->smembTable} - SET level='$level', mid=$mid WHERE id='{$a0['id']}'"); - if(PEAR::isError($r)) return $r; + if ($level < intval($a0['level'])){ + $sql2 = "UPDATE {$this->smembTable} + SET level='$level', mid=$mid WHERE id='{$a0['id']}'"; + $r = $this->dbc->query($sql2); + if (PEAR::isError($r)) { + return $r; + } } - }else{ + } else { $id = $this->dbc->nextId("{$this->smembTable}_id_seq"); - if(PEAR::isError($id)) return $id; - $r = $this->dbc->query(" + if (PEAR::isError($id)) { + return $id; + } + $sql3 = " INSERT INTO {$this->smembTable} (id, uid, gid, level, mid) VALUES ($id, $uid, $gid, $level, $mid) - "); - if(PEAR::isError($r)) return $r; + "; + $r = $this->dbc->query($sql3); + if (PEAR::isError($r)) { + return $r; + } } return $id; - } + } // fn _addMemb + /** - * Remove membership record + * Remove membership record * - * @param mid int - * @return null/err + * @param int $mid + * @return null/err */ function _removeMemb($mid) { - return $this->dbc->query("DELETE FROM {$this->smembTable} - WHERE id='$mid'"); - } + $sql = "DELETE FROM {$this->smembTable} + WHERE id='$mid'"; + return $this->dbc->query($sql); + } // fn _removeMemb + /** - * List [in]direct members of group + * List [in]direct members of group * - * @param gid int - * @param uid int, optional - * @return array/err + * @param int $gid + * @param int $uid, optional + * @return array/err */ function _listMemb($gid, $uid=NULL) { - return $this->dbc->getAll(" + $sql = " SELECT id, uid, level FROM {$this->smembTable} - WHERE gid='$gid'".(is_null($uid) ? '' : " AND uid='$uid'")); - } + WHERE gid='$gid'".(is_null($uid) ? '' : " AND uid='$uid'"); + return $this->dbc->getAll($sql); + } // fn _listMemb + /** - * List groups where uid is [in]direct member + * List groups where uid is [in]direct member * - * @param gid int - * @param uid int, optional - * @return array/err + * @param int $gid + * @param int $uid, optional + * @return array/err */ function _listRMemb($uid, $gid=NULL) { - return $this->dbc->getAll(" + $sql = " SELECT id, gid, level FROM {$this->smembTable} - WHERE uid='$uid'".(is_null($gid) ? '' : " AND gid='$gid'")); - } + WHERE uid='$uid'".(is_null($gid) ? '' : " AND gid='$gid'"); + return $this->dbc->getAll($sql); + } // fn listRMemb + /** - * Add uid and its [in]direct members to gid + * Add uid and its [in]direct members to gid * - * @param uid int - * @param gid int - * @param level int - * @param rmid int // - * @return int/err + * @param int $uid + * @param int $gid + * @param int $level + * @param int $rmid // + * @return int/err */ function _plainAddSubj2Gr($uid, $gid, $level=0, $rmid='null') { $mid = $this->_addMemb($uid, $gid, $level, $rmid); - if(PEAR::isError($mid)) return $mid; - $marr = $this->_listMemb($uid); if(PEAR::isError($marr)) return $marr; - foreach($marr as $k=>$v){ + if (PEAR::isError($mid)) { + return $mid; + } + $marr = $this->_listMemb($uid); + if (PEAR::isError($marr)) { + return $marr; + } + foreach ($marr as $k => $v) { $r = $this->_addMemb( $v['uid'], $gid, intval($v['level'])+$level+1, $mid ); - if(PEAR::isError($r)) return $r; + if (PEAR::isError($r)) { + return $r; + } } return $mid; - } + } // fn _plainAddSubj2Gr + /** - * Rebuild indirect membership records
- * it's probably more complicated to do removing without rebuild ... + * Rebuild indirect membership records
+ * it's probably more complicated to do removing without rebuild ... * - * @return true/err + * @return true/err */ function _rebuildRels() { $this->dbc->query("BEGIN"); $r = $this->dbc->query("LOCK TABLE {$this->smembTable}"); - if(PEAR::isError($r)) return $r; + if (PEAR::isError($r)) { + return $r; + } $r = $this->dbc->query("DELETE FROM {$this->smembTable} WHERE mid is not null"); - if(PEAR::isError($r)) return $r; + if (PEAR::isError($r)) { + return $r; + } $arr = $this->dbc->getAll("SELECT uid, gid FROM {$this->smembTable}"); // WHERE mid is null - if(PEAR::isError($arr)) return $arr; - foreach($arr as $it){ + if (PEAR::isError($arr)) { + return $arr; + } + foreach ($arr as $it) { $marr = $this->_listRMemb($it['gid']); - if(PEAR::isError($marr)) return $marr; - foreach($marr as $k=>$v){ + if (PEAR::isError($marr)) { + return $marr; + } + foreach ($marr as $k => $v) { $r = $this->_plainAddSubj2Gr( $it['uid'], $v['gid'], intval($v['level'])+1, $v['id'] ); - if(PEAR::isError($r)) return $r; + if (PEAR::isError($r)) { + return $r; + } } } $r = $this->dbc->query("COMMIT"); if(PEAR::isError($r)) return $r; return TRUE; - } - + } // fn _rebuildRels + /* =============================================== test and debug methods */ /** - * Dump subjects for debug + * Dump subjects for debug * - * @param indstr string // indentation string - * @param ind string // aktual indentation - * @return string + * @param string $indstr // indentation string + * @param string $ind // aktual indentation + * @return string */ function dumpSubjects($indstr=' ', $ind='') { @@ -473,24 +591,26 @@ class Subjects extends ObjClasses{ $this->getSubjectsWCnt() ))."\n"; return $r; - } - + } // fn dumpSubjects + + /** - * Delete all subjects and membership records + * Delete all subjects and membership records * - * @return void + * @return void */ function deleteData() { $this->dbc->query("DELETE FROM {$this->subjTable}"); $this->dbc->query("DELETE FROM {$this->smembTable}"); parent::deleteData(); - } + } // fn deleteData + /** - * Insert test data + * Insert test data * - * @return array + * @return array */ function testData() { @@ -513,15 +633,18 @@ class Subjects extends ObjClasses{ $this->addSubj2Gr('gr4', 'gr3'); $this->addSubj2Gr('gr3', 'gr2'); return $this->tdata['subjects'] = $o; - } - + } // fn testData + + /** - * Make basic test + * Make basic test * */ function test() { - if(PEAR::isError($p = parent::test())) return $p; + if (PEAR::isError($p = parent::test())) { + return $p; + } $this->deleteData(); $this->testData(); $this->test_correct = "root(0), test1(0), test2(0), test3(0),". @@ -535,17 +658,20 @@ class Subjects extends ObjClasses{ " gr1(0), gr2(1), gr3(1), gr4(1)\n"; $this->test_dump .= $this->dumpSubjects(); $this->deleteData(); - if($this->test_dump == $this->test_correct) - { - $this->test_log.="subj: OK\n"; return TRUE; - }else return PEAR::raiseError( + if ($this->test_dump == $this->test_correct) { + $this->test_log.="subj: OK\n"; + return TRUE; + } else { + return PEAR::raiseError( 'Subjects::test:', 1, PEAR_ERROR_DIE, '%s'. "
\ncorrect:\n{$this->test_correct}\n".
             "dump:\n{$this->test_dump}\n
\n"); - } + } + } // fn test + /** - * Create tables + initialize + * Create tables + initialize * */ function install() @@ -576,13 +702,13 @@ class Subjects extends ObjClasses{ $this->dbc->query("CREATE UNIQUE INDEX {$this->smembTable}_id_idx ON {$this->smembTable} (id)"); $this->dbc->createSequence("{$this->smembTable}_id_seq"); + } // fn install - } /** - * Drop tables etc. + * Drop tables etc. * - * @return void + * @return void */ function uninstall() { @@ -591,6 +717,7 @@ class Subjects extends ObjClasses{ $this->dbc->query("DROP TABLE {$this->smembTable}"); $this->dbc->dropSequence("{$this->smembTable}_id_seq"); parent::uninstall(); - } -} + } // fn uninstall + +} // class Subjects ?> \ No newline at end of file