add: User profile data table is now a flat table.

This commit is contained in:
Doug Bell 2007-05-28 21:35:34 +00:00
parent 8590ef89d5
commit 07a40788bb
41 changed files with 493 additions and 164 deletions

View file

@ -5,6 +5,8 @@
http://www.plainblack.com/rfe/request-for-enhancement/search-asset-feedback.-i.e.-no-results-found#kH5X_YA17ZxbRvi6gx5KRA http://www.plainblack.com/rfe/request-for-enhancement/search-asset-feedback.-i.e.-no-results-found#kH5X_YA17ZxbRvi6gx5KRA
- RFE: JS confirmation Operation/DatabaseLink.pm - RFE: JS confirmation Operation/DatabaseLink.pm
http://www.plainblack.com/rfe/request-for-enhancement/-1493348--js-confirmation-operation/databaselink/re--1493348--js-confirmation-operation/databaselink.pm#OUb5zN8bltGdPG_2LJZMGQ http://www.plainblack.com/rfe/request-for-enhancement/-1493348--js-confirmation-operation/databaselink/re--1493348--js-confirmation-operation/databaselink.pm#OUb5zN8bltGdPG_2LJZMGQ
- add: User profile data table is now a flat table, one column for each
field.

View file

@ -7,6 +7,17 @@ upgrading from one version to the next, or even between multiple
versions. Be sure to heed the warnings contained herein as they will versions. Be sure to heed the warnings contained herein as they will
save you many hours of grief. save you many hours of grief.
7.4.0
--------------------------------------------------------------------
* The userProfileData table has been completely re-done. Now, each
user profile field has its own column in the userProfileData table.
Any applications that you may have that makes raw SQL queries against
the userProfileData table will need to be updated to reflect these
changes.
7.3.16 7.3.16
-------------------------------------------------------------------- --------------------------------------------------------------------

View file

@ -21,6 +21,8 @@ my $quiet; # this line required
my $session = start(); # this line required my $session = start(); # this line required
# upgrade functions go here # upgrade functions go here
fixProfileDataWithoutFields($session);
buildNewUserProfileTable($session);
finish($session); # this line required finish($session); # this line required
@ -32,6 +34,125 @@ finish($session); # this line required
# # and here's our code # # and here's our code
#} #}
#----------------------------------------------------------------------------
sub fixProfileDataWithoutFields {
my $session = shift;
my $db = $session->db;
use WebGUI::ProfileField;
print "\tFixing profile data without entries in userProfileField table..." unless $quiet;
for my $fieldName (qw{ firstDayOfWeek language timeZone uiLevel }) {
next if WebGUI::ProfileField->new($session, $fieldName);
$db->write(
q{INSERT INTO userProfileField (fieldName, label, visible, fieldType, protected, editable)
VALUES (?,?,0,"ReadOnly",1,0)},
[$fieldName, $fieldName]
);
}
print "OK!\n" unless $quiet;
}
#----------------------------------------------------------------------------
sub buildNewUserProfileTable {
my $session = shift;
my $db = $session->db;
print "\tBuilding new user profile table. This may take a while...\n" unless $quiet;
use WebGUI::ProfileField;
use List::Util qw( first );
print "\t\tCreating structure..." unless $quiet;
# Create a new temporary table
$db->write(q{
CREATE TABLE tmp_userProfileData (
userId VARCHAR(22) BINARY NOT NULL,
PRIMARY KEY (userId)
)
});
# Loop through the current fields and add them to the new table
my @profileFields;
my $sth = $db->read(q{SELECT fieldName, fieldType FROM userProfileField});
while (my %fieldData = $sth->hash) {
push @profileFields, $fieldData{fieldName};
my $fieldType = 'WebGUI::Form::'.ucfirst $fieldData{fieldType};
my $fieldName = $db->dbh->quote_identifier($fieldData{fieldName});
eval "use $fieldType;";
my $dataType = $fieldType->new($session)->get("dbDataType");
$db->write(
"ALTER TABLE tmp_userProfileData ADD COLUMN ($fieldName $dataType)"
);
}
print " OK!\n" unless $quiet;
# Find fields that were not in the userProfileField database.
print "\t\tLooking for profile fields not defined in User Profiling... \n" unless $quiet;
my @dataFields = $db->buildArray("SELECT fieldName FROM userProfileData GROUP BY fieldName");
for my $dataField (@dataFields) {
if (!first { $_ eq $dataField } @profileFields) {
print "\t\t\tCreating invisible, read-only profile field '$dataField'\n" unless $quiet;
my $fieldType = 'WebGUI::Form::ReadOnly';
my $fieldName = $db->dbh->quote_identifier($dataField);
eval "use $fieldType;";
my $dataType = $fieldType->new($session)->get("dbDataType");
$db->write(
"ALTER TABLE tmp_userProfileData ADD COLUMN ($fieldName $dataType)"
);
# Create the profile field
WebGUI::ProfileField->create($session, $dataField, {
label => $dataField,
fieldType => "ReadOnly",
visible => 0,
protected => 1,
});
}
}
print "\t\t... Done!\n";
print "\t\tMigrating data to temporary table... " unless $quiet;
# Loop over the old table and put them in the new table
$sth = $db->read(q{SELECT userId FROM users});
while (my $user = $sth->hashRef) {
# Get all of this user's profile data
my %profile
= $db->buildHash(
"SELECT fieldName, fieldData FROM userProfileData WHERE userId=?",
[$user->{userId}]
);
# Write to the temp table
my $sql
= q{INSERT INTO tmp_userProfileData }
. q{(userId,} . join(",", map { $db->dbh->quote_identifier($_) } keys %profile) . q{)}
. q{VALUES (?,} . join(",",("?")x values %profile) . q{)}
;
$db->write($sql, [$user->{userId},values %profile]);
}
$sth->finish;
print "OK!\n" unless $quiet;
# Delete the old table
print "\t\tExchanging old data with new... ";
$db->write("drop table userProfileData");
# Rename the new table
$db->write("rename table tmp_userProfileData to userProfileData");
print "OK!\n" unless $quiet;
print "\t\t... Done!\n" unless $quiet;
}
# ---- DO NOT EDIT BELOW THIS LINE ---- # ---- DO NOT EDIT BELOW THIS LINE ----

View file

@ -31,14 +31,10 @@ sub _fetchNames {
my $self = shift; my $self = shift;
my @userIds = @_; my @userIds = @_;
my %nameHash; my %nameHash;
my $sql = "select users.username, my $sql = "SELECT users.username, users.userId, firstName, lastName
users.userId, FROM users
a.fieldData as firstName, LEFT JOIN userProfileData ON users.userId=userProfileData.userId
b.fieldData as lastName WHERE users.userId=?";
from users
left join userProfileData a on users.userId=a.userId and a.fieldName='firstName'
left join userProfileData b on users.userId=b.userId and b.fieldName='lastName'
where users.userId=?";
my $sth = $self->session->db->prepare($sql); my $sth = $self->session->db->prepare($sql);
foreach my $userId (@userIds) { foreach my $userId (@userIds) {
$sth->execute([ $userId ]); $sth->execute([ $userId ]);
@ -51,7 +47,7 @@ where users.userId=?";
#------------------------------------------------------------------- #-------------------------------------------------------------------
sub _fetchDepartments { sub _fetchDepartments {
my $self = shift; my $self = shift;
return $self->session->db->buildArray("select fieldData from userProfileData where fieldName='department' GROUP by fieldData"); return $self->session->db->buildArray("SELECT department FROM userProfileData GROUP BY department");
} }
@ -244,19 +240,17 @@ sub view {
my $sql = "select users.username, my $sql = "select users.username,
users.userId, users.userId,
a.fieldData as firstName, firstName,
InOutBoard_status.message, InOutBoard_status.message,
b.fieldData as lastName, lastName,
InOutBoard_status.status, InOutBoard_status.status,
InOutBoard_status.dateStamp, InOutBoard_status.dateStamp,
c.fieldData as department, department,
groupings.groupId groupings.groupId
from users from users
left join groupings on groupings.userId=users.userId left join groupings on groupings.userId=users.userId
left join InOutBoard on groupings.groupId=InOutBoard.inOutGroup left join InOutBoard on groupings.groupId=InOutBoard.inOutGroup
left join userProfileData a on users.userId=a.userId and a.fieldName='firstName' left join userProfileData on users.userId=userProfileData.userId
left join userProfileData b on users.userId=b.userId and b.fieldName='lastName'
left join userProfileData c on users.userId=c.userId and c.fieldName='department'
left join InOutBoard_status on users.userId=InOutBoard_status.userId and InOutBoard_status.assetId=".$self->session->db->quote($self->getId())." left join InOutBoard_status on users.userId=InOutBoard_status.userId and InOutBoard_status.assetId=".$self->session->db->quote($self->getId())."
where users.userId<>'1' and InOutBoard.inOutGroup=".$self->session->db->quote($self->get("inOutGroup"))." where users.userId<>'1' and InOutBoard.inOutGroup=".$self->session->db->quote($self->get("inOutGroup"))."
group by userId group by userId
@ -312,14 +306,12 @@ sub www_selectDelegates {
"select "select
users.username, users.username,
users.userId, users.userId,
a.fieldData as firstName, firstName,
b.fieldData as lastName lastName
from users from users
left join groupings on users.userId=groupings.userId left join groupings on users.userId=groupings.userId
left join InOutBoard on groupings.groupId=InOutBoard.inOutGroup left join InOutBoard on groupings.groupId=InOutBoard.inOutGroup
left join userProfileData a on users.userId=a.userId and a.fieldName='firstName' left join userProfileData on users.userId=userProfileData.userId
left join userProfileData b on users.userId=b.userId and b.fieldName='lastName'
left join userProfileData c on users.userId=c.userId and c.fieldName='department'
left join InOutBoard_status on users.userId=InOutBoard_status.userId and InOutBoard_status.assetId=? left join InOutBoard_status on users.userId=InOutBoard_status.userId and InOutBoard_status.assetId=?
where where
users.userId<>'1' users.userId<>'1'
@ -465,19 +457,17 @@ sub www_viewReport {
my $sql = "select users.username, my $sql = "select users.username,
users.userId, users.userId,
a.fieldData as firstName, firstName,
InOutBoard_statusLog.message, InOutBoard_statusLog.message,
b.fieldData as lastName, lastName,
InOutBoard_statusLog.status, InOutBoard_statusLog.status,
InOutBoard_statusLog.dateStamp, InOutBoard_statusLog.dateStamp,
InOutBoard_statusLog.createdBy, InOutBoard_statusLog.createdBy,
c.fieldData as department, department,
groupings.groupId groupings.groupId
from users from users
left join groupings on groupings.userId=users.userId left join groupings on groupings.userId=users.userId
left join userProfileData a on users.userId=a.userId and a.fieldName='firstName' left join userProfileData on users.userId=userProfileData.userId
left join userProfileData b on users.userId=b.userId and b.fieldName='lastName'
left join userProfileData c on users.userId=c.userId and c.fieldName='department'
left join InOutBoard_statusLog on users.userId=InOutBoard_statusLog.userId and InOutBoard_statusLog.assetId=".$self->session->db->quote($self->getId())." left join InOutBoard_statusLog on users.userId=InOutBoard_statusLog.userId and InOutBoard_statusLog.assetId=".$self->session->db->quote($self->getId())."
where users.userId<>'1' and where users.userId<>'1' and
groupings.groupId=".$self->session->db->quote($self->getValue("inOutGroup"))." and groupings.groupId=".$self->session->db->quote($self->getValue("inOutGroup"))." and

View file

@ -270,13 +270,10 @@ sub _userSearchQuery {
my $query = <<"SQL"; my $query = <<"SQL";
SELECT 'user' AS resourceKind, users.userId AS resourceId SELECT 'user' AS resourceKind, users.userId AS resourceId
FROM users FROM users
LEFT JOIN userProfileData AS lastName ON users.userId = lastName.userId LEFT JOIN userProfileData ON users.userId = userProfileData.userId
AND lastName.fieldName = 'lastName' WHERE (LOWER(lastName) LIKE ? OR LOWER(firstName) LIKE ?
LEFT JOIN userProfileData AS firstName ON users.userId = firstName.userId
AND firstName.fieldName = 'firstName'
WHERE (LOWER(lastName.fieldData) LIKE ? OR LOWER(firstName.fieldData) LIKE ?
OR LOWER(users.username) LIKE ?) AND (users.userId NOT IN $excludePlaceholders) OR LOWER(users.username) LIKE ?) AND (users.userId NOT IN $excludePlaceholders)
ORDER BY lastName.fieldData, firstName.fieldData ORDER BY lastName, firstName
SQL SQL
my @placeholders = (($searchPattern) x 3, @exclude); my @placeholders = (($searchPattern) x 3, @exclude);
return ($query, \@placeholders); return ($query, \@placeholders);

View file

@ -651,10 +651,9 @@ sub recoverPasswordFinish {
my @fieldNames = keys %fieldValues; my @fieldNames = keys %fieldValues;
my @fieldValues = values %fieldValues; my @fieldValues = values %fieldValues;
my $joins = join(' ', map{"INNER JOIN userProfileData AS p$_ ON u.userId = p$_.userId AND p$_.fieldName = ".$self->session->db->quote($fieldNames[$_])} (0..$#fieldNames)); my $wheres = join(' ', map{"AND upd.$_ = ?"} (0..$#fieldNames));
my $wheres = join(' ', map{"AND p$_.fieldData = ?"} (0..$#fieldNames));
$wheres .= ' AND u.username = ?' if defined $username; $wheres .= ' AND u.username = ?' if defined $username;
my $sql = "SELECT u.userId FROM users AS u $joins WHERE u.authMethod = 'WebGUI' $wheres"; my $sql = "SELECT u.userId FROM users AS u JOIN userProfileData AS upd ON u.userId=upd.userId WHERE u.authMethod = 'WebGUI' $wheres";
my @userIds = $self->session->db->buildArray($sql, [@fieldValues, (defined($username)? ($username) : ())]); my @userIds = $self->session->db->buildArray($sql, [@fieldValues, (defined($username)? ($username) : ())]);
if (@userIds == 0) { if (@userIds == 0) {

View file

@ -81,6 +81,9 @@ sub definition {
class=>{ class=>{
defaultValue=> undef defaultValue=> undef
}, },
dbDataType => {
defaultValue => "VARCHAR(22) BINARY",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -64,6 +64,9 @@ sub definition {
defaultValue=>{ defaultValue=>{
defaultValue=>$i18n->get(62) defaultValue=>$i18n->get(62)
}, },
dbDataType => {
defaultValue => "VARCHAR(255)",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -72,6 +72,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>0 defaultValue=>0
}, },
dbDataType => {
defaultValue => "VARCHAR(6)",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -85,7 +85,10 @@ sub definition {
}, },
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
} },
dbDataType => {
defaultValue => "TEXT",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -53,6 +53,9 @@ sub definition {
formName=>{ formName=>{
defaultValue=>$i18n->get("color") defaultValue=>$i18n->get("color")
}, },
dbDataType => {
defaultValue => "VARCHAR(7)",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -68,7 +68,10 @@ sub definition {
}, },
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
} },
dbDataType => {
defaultValue => "TEXT",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -159,6 +159,12 @@ A text string that will pop up when the user hovers over the label when toHtmlWi
Flag that tells the User Profile system that this is a valid form element in a User Profile Flag that tells the User Profile system that this is a valid form element in a User Profile
=head4 dbDataType
The SQL data type for this form element. Fields created using this form control
will create a column with this data type. If undef, will not create a database
column. Defaults to "VARCHAR(255)".
=cut =cut
sub definition { sub definition {
@ -216,8 +222,11 @@ sub definition {
}, },
profileEnabled=>{ profileEnabled=>{
defaultValue=>0 defaultValue=>0
}, },
}); dbDataType => {
defaultValue => "VARCHAR(255)",
},
});
return $definition; return $definition;
} }

View file

@ -93,6 +93,9 @@ sub definition {
hoverHelp=>{ hoverHelp=>{
defaultValue=>$i18n->get('1075 description') defaultValue=>$i18n->get('1075 description')
}, },
dbDataType => {
defaultValue => "VARCHAR(22) BINARY",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -101,6 +101,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
}, },
dbDataType => {
defaultValue => "BIGINT",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -96,6 +96,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
}, },
dbDataType => {
defaultValue => "BIGINT",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -87,7 +87,10 @@ sub definition {
}, },
deleteFileUrl=>{ deleteFileUrl=>{
defaultValue=>undef defaultValue=>undef
} },
dbDataType => {
defaultValue => "VARCHAR(22) BINARY",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -79,6 +79,9 @@ sub definition {
defaultValue=>{ defaultValue=>{
defaultValue=>"most", defaultValue=>"most",
}, },
dbDataType => {
defaultValue => "VARCHAR(16)",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -85,6 +85,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
}, },
dbDataType => {
defaultValue => "DOUBLE",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -93,6 +93,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
}, },
dbDataType => {
defaultValue => "VARCHAR(22) BINARY",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -95,6 +95,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
}, },
dbDataType => {
defaultValue => "LONGTEXT",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -72,6 +72,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
}, },
dbDataType => {
defaultValue => "TEXT",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -81,8 +81,11 @@ sub definition {
forceImageOnly=>{ forceImageOnly=>{
defaultValue=>0 defaultValue=>0
}, },
}); dbDataType => {
return $class->SUPER::definition($session, $definition); defaultValue => "VARCHAR(22) BINARY",
},
});
return $class->SUPER::definition($session, $definition);
} }

View file

@ -71,6 +71,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
}, },
dbDataType => {
defaultValue => "BIGINT",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -85,6 +85,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
}, },
dbDataType => {
defaultValue => "BIGINT",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -76,6 +76,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
}, },
dbDataType => {
defaultValue => "BIGINT",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -99,7 +99,10 @@ sub definition {
}, },
afterEdit=>{ afterEdit=>{
defaultValue=>undef defaultValue=>undef
} },
dbDataType => {
defaultValue => "TEXT",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -171,6 +171,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>0 defaultValue=>0
}, },
dbDataType => {
defaultValue => "TEXT",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -84,6 +84,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>1, defaultValue=>1,
}, },
dbDataType => {
defaultValue => "VARCHAR(255)",
}
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -68,18 +68,21 @@ sub definition {
push(@{$definition}, { push(@{$definition}, {
formName=>{ formName=>{
defaultValue=>$i18n->get("484"), defaultValue=>$i18n->get("484"),
}, },
multiple=>{ multiple=>{
defaultValue=>1 defaultValue=>1
}, },
size=>{ size=>{
defaultValue=>5 defaultValue=>5
}, },
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
}, },
}); dbDataType => {
return $class->SUPER::definition($session, $definition); defaultValue => "LONGTEXT",
},
});
return $class->SUPER::definition($session, $definition);
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------

View file

@ -54,6 +54,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
}, },
dbDataType => {
defaultValue => "TEXT",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -79,6 +79,9 @@ sub definition {
namespace=>{ namespace=>{
defaultValue=>undef defaultValue=>undef
}, },
dbDataType => {
defaultValue => "VARCHAR(22) BINARY",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -92,6 +92,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
}, },
dbDataType => {
defaultValue => "LONGTEXT",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -90,6 +90,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
}, },
dbDataType => {
defaultValue => "BIGINT",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -81,6 +81,9 @@ sub definition {
readOnly=>{ readOnly=>{
defaultValue=>0, defaultValue=>0,
}, },
dbDataType => {
defaultValue => "VARCHAR(22) BINARY",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -85,7 +85,10 @@ sub definition {
}, },
none=>{ none=>{
defaulValue=>0 defaulValue=>0
} },
dbDataType => {
defaultValue => "VARCHAR(22) BINARY",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -72,6 +72,9 @@ sub definition {
profileEnabled=>{ profileEnabled=>{
defaultValue=>1 defaultValue=>1
}, },
dbDataType => {
defaultValue => "INT(1)",
},
}); });
return $class->SUPER::definition($session, $definition); return $class->SUPER::definition($session, $definition);
} }

View file

@ -84,10 +84,14 @@ email address to check for duplication
=cut =cut
sub isDuplicateEmail { sub isDuplicateEmail {
my $session = shift; my $session = shift;
my $email = shift; my $email = shift;
my ($otherEmail) = $session->db->quickArray("select count(*) from userProfileData where fieldName='email' and fieldData = ".$session->db->quote($email)." and userId <> ".$session->db->quote($session->user->userId)); my ($otherEmail)
return ($otherEmail > 0); = $session->db->quickArray(
'select count(*) from userProfileData where email = ? and userId <> ?',
[$email, $session->user->userId]
);
return ($otherEmail > 0);
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------

View file

@ -138,10 +138,9 @@ sub doUserSearch {
} }
$keyword = $session->db->quote($keyword); $keyword = $session->db->quote($keyword);
my $sql = "select users.userId, users.username, users.status, users.dateCreated, users.lastUpdated, my $sql = "select users.userId, users.username, users.status, users.dateCreated, users.lastUpdated,
email.fieldData as email from users userProfileData.email from users
left join userProfileData email on users.userId=email.userId and email.fieldName='email' left join userProfileData on users.userId=userProfileData.userId
left join userProfileData useralias on users.userId=useralias.userId and useralias.fieldName='alias' where $selectedStatus and (users.username like ".$keyword." or alias like ".$keyword." or email like ".$keyword.")
where $selectedStatus and (users.username like ".$keyword." or useralias.fieldData like ".$keyword." or email.fieldData like ".$keyword.")
and users.userId not in (".$session->db->quoteAndJoin($userFilter).") order by users.username"; and users.userId not in (".$session->db->quoteAndJoin($userFilter).") order by users.username";
if ($returnPaginator) { if ($returnPaginator) {
my $p = WebGUI::Paginator->new($session,$session->url->page("op=".$op)); my $p = WebGUI::Paginator->new($session,$session->url->page("op=".$op));

View file

@ -94,20 +94,45 @@ The unique id of the category to assign this field to. Defaults to "1" (misc).
=cut =cut
sub create { sub create {
my $class = shift; my $class = shift;
my $session = shift; my $session = shift;
my $fieldName = shift; my $fieldName = shift;
my $properties = shift; my $properties = shift;
my $categoryId = shift || "1"; my $categoryId = shift || "1";
my $fieldNameExists = $session->db->quickScalar("select count(*) from userProfileField where fieldName=?", [$fieldName]);
return undef if $fieldNameExists; my $db = $session->db;
return undef if $class->isReservedFieldName($fieldName);
my $id = $session->db->setRow("userProfileField","fieldName",{fieldName=>"new"},$fieldName); ### Check data
my $self = $class->new($session,$id); # Check if the field already exists
$self->setCategory($categoryId); my $fieldNameExists
$self->set($properties); = $session->db->quickScalar(
return $self; "select count(*) from userProfileField where fieldName=?",
[$fieldName]
);
return undef if $fieldNameExists;
return undef if $class->isReservedFieldName($fieldName);
### Data okay, create the field
# Add the record
my $id
= $session->db->setRow("userProfileField","fieldName",{fieldName=>"new"},$fieldName);
my $self = $class->new($session,$id);
# Get the field's data type
my $formClass = 'WebGUI::Form::' . ucfirst $properties->{fieldType};
eval "use $formClass;";
my $dbDataType = $formClass->new($session, $self->_formProperties($properties))->get("dbDataType");
# Add the column to the userProfileData table
$db->write(
"ALTER TABLE userProfileData ADD " . $db->dbh->quote_identifier($fieldName)
. $dbDataType
);
$self->setCategory($categoryId);
$self->set($properties);
return $self;
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------
@ -119,19 +144,31 @@ Deletes this field and all user data attached to it.
=cut =cut
sub delete { sub delete {
my $self = shift; my $self = shift;
$self->session->db->write("delete from userProfileData where fieldName=?", [$self->getId]); my $db = $self->session->db;
$self->session->db->deleteRow("userProfileField","fieldName",$self->getId);
# Remove the column from the userProfileData table
$db->write("ALTER TABLE userProfileData DROP " . $self->getId);
# Remove the record
$db->deleteRow("userProfileField","fieldName",$self->getId);
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------
# Get a hashref of properties to give to a WebGUI::Form::Control
sub _formProperties { sub _formProperties {
my $self = shift; my $self = shift;
my $properties = shift || {}; my $properties = shift || {};
$properties->{label} = $self->getLabel unless $properties->{label};
$properties->{fieldType} = $self->get("fieldType"); # Make a copy of the properties so we don't clobber them
$properties->{name} = $self->getId; my %properties = %{$properties};
my $values = WebGUI::Operation::Shared::secureEval($self->session,$self->get("possibleValues"));
$properties{ label } = $self->getLabel unless $properties->{label};
$properties{ fieldType } = $self->get("fieldType");
$properties{ name } = $self->getId;
my $values
= WebGUI::Operation::Shared::secureEval($self->session,$self->get("possibleValues"));
unless (ref $values eq 'HASH') { unless (ref $values eq 'HASH') {
if ($self->get('possibleValues') =~ /\S/) { if ($self->get('possibleValues') =~ /\S/) {
$self->session->errorHandler->warn("Could not get a hash out of possible values for profile field ".$self->getId); $self->session->errorHandler->warn("Could not get a hash out of possible values for profile field ".$self->getId);
@ -140,13 +177,13 @@ sub _formProperties {
} }
my $orderedValues = {}; my $orderedValues = {};
tie %{$orderedValues}, 'Tie::IxHash'; tie %{$orderedValues}, 'Tie::IxHash';
foreach my $ov (sort keys %{$values}) { for my $ov (sort keys %{$values}) {
$orderedValues->{$ov} = $values->{$ov}; $orderedValues->{$ov} = $values->{$ov};
} }
$properties->{options} = $orderedValues; $properties{ options } = $orderedValues;
$properties->{forceImageOnly} = $self->get("forceImageOnly"); $properties{ forceImageOnly } = $self->get("forceImageOnly");
$properties->{dataDefault} = $self->get("dataDefault"); $properties{ dataDefault } = $self->get("dataDefault");
return $properties; return \%properties;
} }
=head2 formField ( [ formProperties, withWrapper, userObject ] ) =head2 formField ( [ formProperties, withWrapper, userObject ] )
@ -334,6 +371,19 @@ sub getFields {
#------------------------------------------------------------------- #-------------------------------------------------------------------
=head2 getFormControlClass
Returns the full class name of the form control for this profile field.
=cut
sub getFormControlClass {
my $self = shift;
return "WebGUI::Form::" . ucfirst $self->get("fieldType");
}
#-------------------------------------------------------------------
=head2 getRequiredFields ( session ) =head2 getRequiredFields ( session )
Returns an array reference of WebGUI::ProfileField objects that are marked "required". This is a class method. Returns an array reference of WebGUI::ProfileField objects that are marked "required". This is a class method.
@ -484,15 +534,15 @@ The unique name of this field.
=cut =cut
sub new { sub new {
my $class = shift; my $class = shift;
my $session = shift; my $session = shift;
my $id = shift; my $id = shift;
return undef unless ($id); return undef unless ($id);
return undef if $class->isReservedFieldName($id); return undef if $class->isReservedFieldName($id);
my $properties = $session->db->getRow("userProfileField","fieldName",$id); my $properties = $session->db->getRow("userProfileField","fieldName",$id);
# Reject properties that don't exist. # Reject properties that don't exist.
return undef unless scalar keys %$properties; return undef unless scalar keys %$properties;
bless {_session=>$session, _properties=>$properties}, $class; bless {_session=>$session, _properties=>$properties}, $class;
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------
@ -508,14 +558,40 @@ The new name this field should take.
=cut =cut
sub rename { sub rename {
my $self = shift; my $self = shift;
my $newName = shift; my $newName = shift;
my ($fieldNameExists) = $self->session->db->quickArray("select count(*) from userProfileField where fieldName=".$self->session->db->quote($newName));
my $session = $self->session;
my $db = $session->db;
### Check data
# Make sure the field doesn't exist
my $fieldNameExists
= $self->session->db->quickScalar(
"SELECT COUNT(*) FROM userProfileField WHERE fieldName=?",
[$newName]
);
return 0 if ($fieldNameExists); return 0 if ($fieldNameExists);
$self->session->db->write("update userProfileData set fieldName=".$self->session->db->quote($newName)." where fieldName=".$self->session->db->quote($self->getId));
$self->session->db->write("update userProfileField set fieldName=".$self->session->db->quote($newName)." where fieldName=".$self->session->db->quote($self->getId)); # Rename the userProfileData column
my $fieldClass = $self->getFormControlClass;
eval "use $fieldClass;";
my $dbDataType = $fieldClass->new($session, $self->_formProperties)->get("dbDataType");
$self->session->db->write(
"ALTER TABLE userProfileData "
. "CHANGE " . $db->dbh->quote_identifier($self->getId)
. $db->dbh->quote_identifier($newName) . " " . $dbDataType
);
# Update the record
$self->session->db->write(
"update userProfileField set fieldName=? where fieldName=?",
[$newName, $self->getId]
);
$self->{_properties}{fieldName} = $newName; $self->{_properties}{fieldName} = $newName;
return 1;
return 1;
} }
@ -577,9 +653,14 @@ A scalar containing an array reference or scalar declaration of defaultly select
=cut =cut
sub set { sub set {
my $self = shift; my $self = shift;
my $properties = shift; my $properties = shift;
$properties->{visible} = 0 unless ($properties->{visible} == 1);
my $session = $self->session;
my $db = $session->db;
# Set the defaults
$properties->{visible} = 0 unless ($properties->{visible} == 1);
$properties->{editable} = 0 unless ($properties->{editable} == 1); $properties->{editable} = 0 unless ($properties->{editable} == 1);
$properties->{protected} = 0 unless ($properties->{protected} == 1); $properties->{protected} = 0 unless ($properties->{protected} == 1);
$properties->{required} = 0 unless ($properties->{required} == 1); $properties->{required} = 0 unless ($properties->{required} == 1);
@ -594,7 +675,26 @@ sub set {
} }
} }
$properties->{fieldName} = $self->getId; $properties->{fieldName} = $self->getId;
$self->session->db->setRow("userProfileField","fieldName",$properties);
# If the fieldType has changed, modify the userProfileData column
if ($properties->{fieldType} ne $self->get("fieldType")) {
# Create a copy of the new properties so we don't mess them up
my $fieldClass = "WebGUI::Form::".ucfirst($properties->{fieldType});
eval "use $fieldClass;";
my $dbDataType
= $fieldClass->new($session, $self->_formProperties($properties))->get("dbDataType");
my $sql
= "ALTER TABLE userProfileData MODIFY COLUMN "
. $db->dbh->quote_identifier($self->getId) . q{ }
. $dbDataType
;
$db->write($sql);
}
# Update the record
$db->setRow("userProfileField","fieldName",$properties);
foreach my $key (keys %{$properties}) { foreach my $key (keys %{$properties}) {
$self->{_properties}{$key} = $properties->{$key}; $self->{_properties}{$key} = $properties->{$key};
} }

View file

@ -58,12 +58,13 @@ These methods are available from this class:
#------------------------------------------------------------------- #-------------------------------------------------------------------
sub _create { sub _create {
my $session = shift; my $session = shift;
my $userId = shift || $session->id->generate(); my $userId = shift || $session->id->generate();
$session->db->write("insert into users (userId,dateCreated) values (?,?)",[$userId, time()]); $session->db->write("insert into users (userId,dateCreated) values (?,?)",[$userId, time()]);
WebGUI::Group->new($session,2)->addUsers([$userId]); $session->db->write("INSERT INTO userProfileData (userId) VALUES (?)",[$userId]);
WebGUI::Group->new($session,7)->addUsers([$userId]); WebGUI::Group->new($session,2)->addUsers([$userId]);
return $userId; WebGUI::Group->new($session,7)->addUsers([$userId]);
return $userId;
} }
#------------------------------------------------------------------- #-------------------------------------------------------------------
@ -375,41 +376,45 @@ A unique ID to use instead of the ID that WebGUI will generate for you. It must
=cut =cut
sub new { sub new {
my $class = shift; my $class = shift;
my $session = shift; my $session = shift;
my $userId = shift || 1; my $userId = shift || 1;
my $overrideId = shift; my $overrideId = shift;
$userId = _create($session, $overrideId) if ($userId eq "new"); $userId = _create($session, $overrideId) if ($userId eq "new");
my $cache = WebGUI::Cache->new($session,["user",$userId]); my $cache = WebGUI::Cache->new($session,["user",$userId]);
my $userData = $cache->get; my $userData = $cache->get;
unless ($userData->{_userId} && $userData->{_user}{username}) { unless ($userData->{_userId} && $userData->{_user}{username}) {
my %user; my %user;
tie %user, 'Tie::CPHash'; tie %user, 'Tie::CPHash';
%user = $session->db->quickHash("select * from users where userId=?",[$userId]); %user = $session->db->quickHash("select * from users where userId=?",[$userId]);
my %profile = $session->db->buildHash("select userProfileField.fieldName, userProfileData.fieldData my %profile
from userProfileField, userProfileData where userProfileField.fieldName=userProfileData.fieldName and = $session->db->quickHash(
userProfileData.userId=?",[$user{userId}]); "select * from userProfileData where userId=?",
my %default = $session->db->buildHash("select fieldName, dataDefault from userProfileField"); [$user{userId}]
foreach my $key (keys %default) { );
my $value; delete $profile{userId};
if ($profile{$key} eq "" && $default{$key}) {
$value = eval($default{$key}); my %default = $session->db->buildHash("select fieldName, dataDefault from userProfileField");
if (ref $value eq "ARRAY") { foreach my $key (keys %default) {
$profile{$key} = $$value[0]; my $value;
} else { if ($profile{$key} eq "" && $default{$key}) {
$profile{$key} = $value; $value = eval($default{$key});
} if (ref $value eq "ARRAY") {
} $profile{$key} = $$value[0];
} } else {
$profile{alias} = $user{username} if ($profile{alias} =~ /^\W+$/ || $profile{alias} eq ""); $profile{$key} = $value;
$userData = { }
_userId => $userId, }
_user => \%user, }
_profile => \%profile $profile{alias} = $user{username} if ($profile{alias} =~ /^\W+$/ || $profile{alias} eq "");
}; $userData = {
$cache->set($userData, 60*60*24); _userId => $userId,
} _user => \%user,
$userData->{_session} = $session; _profile => \%profile
};
$cache->set($userData, 60*60*24);
}
$userData->{_session} = $session;
bless $userData, $class; bless $userData, $class;
} }
@ -433,7 +438,7 @@ sub newByEmail {
my $class = shift; my $class = shift;
my $session = shift; my $session = shift;
my $email = shift; my $email = shift;
my ($id) = $session->dbSlave->quickArray("select userId from userProfileData where fieldName='email' and fieldData=?",[$email]); my ($id) = $session->dbSlave->quickArray("select userId from userProfileData where email=?",[$email]);
my $user = $class->new($session, $id); my $user = $class->new($session, $id);
return undef if ($user->userId eq "1"); # visitor is never valid for this method return undef if ($user->userId eq "1"); # visitor is never valid for this method
return undef unless $user->username; return undef unless $user->username;
@ -458,22 +463,24 @@ The value to set the profile field name to.
=cut =cut
sub profileField { sub profileField {
my ($self, $fieldName, $value); my $self = shift;
$self = shift; my $fieldName = shift;
$fieldName = shift; my $value = shift;
$value = shift; my $db = $self->session->db;
if (!exists $self->{_profile}{$fieldName} && !$self->session->db->quickScalar("SELECT COUNT(*) FROM userProfileField WHERE fieldName = ?", [$fieldName]) ) { if (!exists $self->{_profile}{$fieldName} && !$self->session->db->quickScalar("SELECT COUNT(*) FROM userProfileField WHERE fieldName = ?", [$fieldName]) ) {
$self->session->errorHandler->warn("No such profile field: $fieldName"); $self->session->errorHandler->warn("No such profile field: $fieldName");
return undef; return undef;
} }
if (defined $value) { if (defined $value) {
$self->uncache; $self->uncache;
$self->{_profile}{$fieldName} = $value; $self->{_profile}{$fieldName} = $value;
$self->session->db->write("delete from userProfileData where userId=? and fieldName=?",[$self->{_userId}, $fieldName]); $db->write(
$self->session->db->write("insert into userProfileData values (?,?,?)", [$self->{_userId}, $fieldName,$value]); "UPDATE userProfileData SET ".$db->dbh->quote_identifier($fieldName)."=? WHERE userId=?",
my $time = $self->session->datetime->time(); [$value, $self->{_userId}]
$self->{_user}{"lastUpdated"} = $time; );
$self->session->db->write("update users set lastUpdated=? where userId=?", [$time, $self->{_userId}]); my $time = $self->session->datetime->time;
$self->{_user}{"lastUpdated"} = $time;
$self->session->db->write("update users set lastUpdated=? where userId=?", [$time, $self->{_userId}]);
} }
return $self->{_profile}{$fieldName}; return $self->{_profile}{$fieldName};
} }