From 615e0e37461fa80dda89bc005b01bc5c45ea7d91 Mon Sep 17 00:00:00 2001 From: Frank Dillon Date: Wed, 12 Nov 2008 23:03:42 +0000 Subject: [PATCH] lots of changes --- docs/upgrades/upgrade_7.6.1-7.6.2.pl | 132 +++- etc/WebGUI.conf.original | 2 + lib/WebGUI/Account.pm | 116 +++- lib/WebGUI/Account/Friends.pm | 4 +- lib/WebGUI/Account/Inbox.pm | 763 ++++++++++++++++++++- lib/WebGUI/Account/Profile.pm | 466 ++++++++++++- lib/WebGUI/Account/User.pm | 4 +- lib/WebGUI/Content/Account.pm | 97 ++- lib/WebGUI/Form/File.pm | 8 + lib/WebGUI/Form/Image.pm | 5 +- lib/WebGUI/Group.pm | 42 +- lib/WebGUI/Inbox.pm | 430 ++++++++++-- lib/WebGUI/Inbox/Message.pm | 320 ++++++++- lib/WebGUI/Macro/FileUrl.pm | 40 +- lib/WebGUI/Operation/Inbox.pm | 48 +- lib/WebGUI/Operation/Profile.pm | 22 +- lib/WebGUI/Operation/ProfileSettings.pm | 15 +- lib/WebGUI/Operation/Settings.pm | 22 +- lib/WebGUI/Paginator.pm | 1 + lib/WebGUI/ProfileCategory.pm | 19 + lib/WebGUI/ProfileField.pm | 69 +- lib/WebGUI/Storage.pm | 5 +- lib/WebGUI/User.pm | 73 +- lib/WebGUI/i18n/English/Account_Inbox.pm | 269 ++++++++ lib/WebGUI/i18n/English/Account_Profile.pm | 71 +- lib/WebGUI/i18n/English/WebGUI.pm | 40 ++ lib/WebGUI/i18n/English/WebGUIProfile.pm | 10 + www/extras/FileUploadControl.js | 2 +- 28 files changed, 2883 insertions(+), 212 deletions(-) diff --git a/docs/upgrades/upgrade_7.6.1-7.6.2.pl b/docs/upgrades/upgrade_7.6.1-7.6.2.pl index 05f298be1..7cae6ebd9 100644 --- a/docs/upgrades/upgrade_7.6.1-7.6.2.pl +++ b/docs/upgrades/upgrade_7.6.1-7.6.2.pl @@ -21,6 +21,7 @@ use WebGUI::Session; use WebGUI::Storage; use WebGUI::Asset; use WebGUI::Utility; +use Tie::IxHash; my $toVersion = '7.6.2'; @@ -40,9 +41,20 @@ addProfileExtrasField($session); addWorkflowToDataform( $session ); installDataTableAsset( $session ); installAjaxI18N( $session ); +fixFriendsGroups( $session ); upgradeAccount( $session ); finish($session); # this line required +#---------------------------------------------------------------------------- +sub fixFriendsGroups { + my $session = shift; + my $users = $session->db->buildArrayRef("select userId from users where friendsGroup is not null && friendsGroup != ''"); + foreach my $userId (@{$users}) { + #purge the admin group + WebGUI::User->new($session,$userId)->friends->deleteGroups([3]); + } +} + #---------------------------------------------------------------------------- sub upgradeAccount { my $session = shift; @@ -52,25 +64,29 @@ sub upgradeAccount { print "\tUpgrading WebGUI Account System... " unless $quiet; #Add account properties to config file $session->config->delete("account"); #Delete account if it exists - $session->config->set("account",{ - profile => { - title => "^International(title,Account_Profile);", - className => "WebGUI::Account::Profile", - }, - friends => { - title => "^International(title,Account_Friends);", - className => "WebGUI::Account::Friends", - }, - user => { - title => "^International(title,Account_User);", - className => "WebGUI::Account::User", + $session->config->set("account",[ + { + identifier => "profile", + title => "^International(title,Account_Profile);", + className => "WebGUI::Account::Profile" }, - inbox => { - title => "^International(title,Account_Inbox);", - className => "WebGUI::Account::Inbox", - } - }); - + { + identifier => "inbox", + title => "^International(title,Account_Inbox);", + className => "WebGUI::Account::Inbox" + }, + { + identifier => "friends", + title => "^International(title,Account_Friends);", + className => "WebGUI::Account::Friends" + }, + { + identifier => "user", + title => "^International(title,Account_User);", + className => "WebGUI::Account::User" + }, + ]); + $session->config->set("profileModuleIdentifier","profile"); #Add the content handler to the config file if it's not there my $oldHandlers = $session->config->get( "contentHandlers" ); unless (isIn("WebGUI::Content::Account",@{$oldHandlers})) { @@ -84,10 +100,84 @@ sub upgradeAccount { $session->config->set( "contentHandlers", \@newHandlers ); } - #Add the settings + #Add the settings for the profile $setting->add("profileStyleTemplateId",""); #Use the userStyle by default - $session->setting->add("profileLayoutTempalteId","FJbUTvZ2nUTn65LpW6gjsA"); - $session->setting->add("profileViewTemplateId","75CmQgpcCSkdsL-oawdn3Q"); + $setting->add("profileLayoutTemplateId","N716tpSna0iIQTKxS4gTWA"); + $setting->add("profileEditLayoutTemplateId","FJbUTvZ2nUTn65LpW6gjsA"); + $setting->add("profileEditTemplateId","75CmQgpcCSkdsL-oawdn3Q"); + $setting->add("profileViewTempalteId","2CS-BErrjMmESOtGT90qOg"); + + #Add the settings for the inbox + $setting->add("inboxStyleTemplateId",""); #Use the userStyle by default + $setting->add("inboxLayoutTempalteId","N716tpSna0iIQTKxS4gTWA"); + $setting->add("inboxViewTemplateId","c8xrwVuu5QE0XtF9DiVzLw"); + $setting->add("inboxViewMessageTemplateId","0n4HtbXaWa_XJHkFjetnLQ"); + $setting->add("inboxSendMessageTemplateId","6uQEULvXFgCYlRWnYzZsuA"); + $setting->add("inboxErrorTemplateId","ErEzulFiEKDkaCDVmxUavw"); + $setting->add("inboxInvitationErrorTemplateId","5A8Hd9zXvByTDy4x-H28qw"); + $setting->add("inboxMessageConfirmationTemplateId","DUoxlTBXhVS-Zl3CFDpt9g"); + $setting->add("inboxManageInvitationsTemplateId","1Q4Je3hKCJzeo0ZBB5YB8g"); + + #Add inbox changes + $session->db->write(q{ + create table inbox_messageState ( + messageId char(22) binary not null, + userId char(22) binary not null, + isRead tinyint(4) not null default 0, + repliedTo tinyint(4) not null default 0, + deleted tinyint(4) not null default 0, + primary key (messageId, userId) + ) + }); + + #Update the inbox + my $sth = $session->db->read("select messageId, groupId, userId, status from inbox"); + while(my ($messageId,$groupId,$userId,$status) = $sth->array) { + my $repliedTo = $status eq "replied"; + my $isRead = ($status ne "unread" && $status ne "pending")?1:0; + my $deleted = 0; + + if($status eq "deleted") { + #Purge deleted messages + $session->db->write("delete from inbox where messageId=?",[$messageId]); + next; + } + + if($groupId) { + my $g = WebGUI::Group->new($session,$groupId); + my $users = $g->getAllUsers; + foreach my $userId (@{$users}) { + $session->db->write( + q{ REPLACE INTO inbox_messageState (messageId,userId,isRead,repliedTo,deleted) VALUES (?,?,?,?,?) }, + [$messageId,$userId,$isRead,$repliedTo,$deleted] + ); + } + } + + if($userId) { + $session->db->write( + q{ REPLACE INTO inbox_messageState (messageId,userId,isRead,repliedTo,deleted) VALUES (?,?,?,?,?) }, + [$messageId,$userId,$isRead,$repliedTo,$deleted] + ); + } + + if($status ne "completed" && $status ne "pending") { + $session->db->write( + q{ UPDATE inbox SET status='active' WHERE messageId=? }, + [$messageId] + ); + } + } + + #Add the profile field changes + $session->db->write(q{alter table userProfileCategory add column shortLabel char(255) default NULL after label}); + $session->db->write(q{update userProfileCategory set shortLabel='WebGUI::International::get("misc info short","WebGUI");' where profileCategoryId='1'}); + $session->db->write(q{update userProfileCategory set shortLabel='WebGUI::International::get("contact info short","WebGUI");' where profileCategoryId='2'}); + $session->db->write(q{update userProfileCategory set shortLabel='WebGUI::International::get("personal info short","WebGUI");' where profileCategoryId='3'}); + $session->db->write(q{update userProfileCategory set shortLabel='WebGUI::International::get("preferences short","WebGUI");' where profileCategoryId='4'}); + $session->db->write(q{update userProfileCategory set shortLabel='WebGUI::International::get("home info short","WebGUI");' where profileCategoryId='5'}); + $session->db->write(q{update userProfileCategory set shortLabel='WebGUI::International::get("work info short","WebGUI");' where profileCategoryId='6'}); + $session->db->write(q{update userProfileCategory set shortLabel='WebGUI::International::get("demographic info short","WebGUI");' where profileCategoryId='7'}); print "DONE!\n" unless $quiet; } diff --git a/etc/WebGUI.conf.original b/etc/WebGUI.conf.original index e1163d4bb..e4ef49be4 100644 --- a/etc/WebGUI.conf.original +++ b/etc/WebGUI.conf.original @@ -831,9 +831,11 @@ "WebGUI::Content::Referral", "WebGUI::Content::AssetManager", "WebGUI::Content::AssetDiscovery", + "WebGUI::Content::AjaxI18N", "WebGUI::Content::Operation", "WebGUI::Content::Setup", "WebGUI::Content::Shop", + "WebGUI::Content::SiteIndex", "WebGUI::Content::Asset", "WebGUI::Content::NotFound" ], diff --git a/lib/WebGUI/Account.pm b/lib/WebGUI/Account.pm index de38f603e..82cc50d6a 100644 --- a/lib/WebGUI/Account.pm +++ b/lib/WebGUI/Account.pm @@ -18,7 +18,9 @@ This is the class which is used to display a users's profile information =head1 SYNOPSIS - use WebGUI::Account::Profile; + use base 'WebGUI::Account'; + + currentState("edit"); =head1 METHODS @@ -27,6 +29,20 @@ These subroutines are available from this package: =cut readonly session => my %session; +public store => my %store; #This is an all purpose hash to store stuff in: $store{id $self}->{something} = "something" + +#------------------------------------------------------------------- + +=head2 canView ( ) + + Override this method to create permission levels for your Account Pluggin + +=cut + +sub canView { + my $self = shift; + return 1; +} #------------------------------------------------------------------- @@ -36,7 +52,7 @@ readonly session => my %session; =cut -sub editUserSettingsForm { +sub editSettingsForm { my $self = shift; return ""; } @@ -49,12 +65,11 @@ sub editUserSettingsForm { =cut -sub editUserSettingsFormSave { +sub editSettingsFormSave { my $self = shift; return ""; } - #------------------------------------------------------------------- =head2 getLayoutTemplateId ( ) @@ -65,7 +80,7 @@ sub editUserSettingsFormSave { sub getLayoutTemplateId { my $self = shift; - return "FJbUTvZ2nUTn65LpW6gjsA"; + return "N716tpSna0iIQTKxS4gTWA"; } #------------------------------------------------------------------- @@ -81,6 +96,49 @@ sub getStyleTemplateId { return $self->session->setting->get("userFunctionStyleId"); } + +#------------------------------------------------------------------- + +=head2 getUrl ( [pairs,appendUID] ) + + Builds the url for the current page. + +=head3 pairs + + name value pairs to append to the page url. If pairs is not passed in + the current module and do values will be used. + +=head3 appendUID + + If this flag is set and uid is passed along the url, the uid passed in will be + appended to the end of it to the end of the url + +=cut + +sub getUrl { + my $self = shift; + my $pairs = shift; + my $appendUID = shift; + + my $session = $self->session; + my $form = $session->form; + + if($pairs) { + #Append op=account to the url if it doesn't already exist + unless ($pairs =~ m/op=account/){ + $pairs = "op=account;".$pairs; + } + } + else { + $pairs = q{op=account;module=}.$form->get("module").q{;do=}.$form->get("do"); + } + + my $uid = $form->get("uid"); + $pairs .= ";uid=".$uid if($appendUID && $uid); + + return $session->url->page($pairs); +} + #------------------------------------------------------------------- =head2 new ( $session ) @@ -105,9 +163,10 @@ sub new { ); } - my $self = register $class; - my $id = id $self; - $session { $id } = $session; + my $self = register $class; + my $id = id $self; + $session { $id } = $session; + $store { $id } = {}; return $self; } @@ -144,7 +203,7 @@ sub processTemplate { # Sanity checks if (ref $var ne "HASH") { $session->log->error("First argument to processTemplate() should be a hash reference."); - my $i18n = WebGUI::International->new($self->session, 'Account'); + my $i18n = WebGUI::International->new($session, 'Account'); return sprintf($i18n->get('Error: Cannot instantiate template'),$templateId,$className); } @@ -152,7 +211,7 @@ sub processTemplate { unless (defined $template) { $session->log->error("Can't instantiate template $templateId for class ".$className); - my $i18n = WebGUI::International->new($self->session, 'Account'); + my $i18n = WebGUI::International->new($session, 'Account'); return sprintf($i18n->get('Error: Cannot instantiate template'),$templateId,$className); } @@ -160,4 +219,41 @@ sub processTemplate { } +#------------------------------------------------------------------- + +=head2 showError ( vars ) + + Returns a general error screen with the message passed in. + +=head3 vars + +Variable hash ref to append errors to + +=head3 error + +Error message to display + +=head3 url + +URL to display to the user to go back to a safe place + +=head3 templateId + +temlateId to use to display error + +=cut + +sub showError { + my $self = shift; + + my $var = shift || {}; + $var->{'error_message'} = shift; + $var->{'back_url' } = shift; + + my $templateId = shift; + + return $self->processTemplate($var,$templateId) +} + + 1; diff --git a/lib/WebGUI/Account/Friends.pm b/lib/WebGUI/Account/Friends.pm index 10e219eab..77e4fe034 100644 --- a/lib/WebGUI/Account/Friends.pm +++ b/lib/WebGUI/Account/Friends.pm @@ -35,7 +35,7 @@ These subroutines are available from this package: =cut -sub editUserSettingsForm { +sub editSettingsForm { my $self = shift; my $session = $self->session; my $setting = $session->setting; @@ -61,7 +61,7 @@ sub editUserSettingsForm { =cut -sub editUserSettingsFormSave { +sub editSettingsFormSave { } #------------------------------------------------------------------- diff --git a/lib/WebGUI/Account/Inbox.pm b/lib/WebGUI/Account/Inbox.pm index 3ec4ea23f..7f36efd1f 100644 --- a/lib/WebGUI/Account/Inbox.pm +++ b/lib/WebGUI/Account/Inbox.pm @@ -2,6 +2,7 @@ package WebGUI::Account::Inbox; use strict; +use WebGUI::Form; use WebGUI::Exception; use WebGUI::International; use WebGUI::Pluggable; @@ -27,6 +28,51 @@ These subroutines are available from this package: =cut +#------------------------------------------------------------------- + +=head2 appendCommonVars ( var, inbox ) + + Appends common template variables that all inbox templates use + +=head3 var + + The hash reference to append template variables to + +=head3 inbox + + The instance of the inbox currently being worked with. + +=cut + +sub appendCommonVars { + my $self = shift; + my $var = shift; + my $inbox = shift; + my $session = $self->session; + my $user = $session->user; + + $var->{'user_full_name' } = $user->getWholeName; + $var->{'user_member_since' } = $user->dateCreated; + $var->{'view_profile_url' } = $user->getProfileUrl; + $var->{'view_inbox_url' } = $self->getUrl("module=inbox;do=view"); + $var->{'view_invitations_url'} = $self->getUrl("module=inbox;do=manageInvitations"); + $var->{'unread_message_count'} = $inbox->getUnreadMessageCount; + +} + +#------------------------------------------------------------------- + +=head2 canView ( ) + + Returns whether or not the user can view the inbox tab + +=cut + +sub canView { + my $self = shift; + return ($self->session->form->get("uid") eq ""); +} + #------------------------------------------------------------------- =head2 editSettingsForm ( ) @@ -35,20 +81,76 @@ These subroutines are available from this package: =cut -sub editUserSettingsForm { +sub editSettingsForm { my $self = shift; my $session = $self->session; my $setting = $session->setting; my $i18n = WebGUI::International->new($session,'Account_Inbox'); my $f = WebGUI::HTMLForm->new($session); -# $f->template( -# name => "profileStyleTemplateId", -# value => $self->getStyleTemplateId, -# namespace => "style", -# label => $i18n->get("profile style template label"), -# hoverHelp => $i18n->get("profile style template hoverHelp") -# ); + $f->template( + name => "inboxStyleTemplateId", + value => $self->getStyleTemplateId, + namespace => "style", + label => $i18n->get("inbox style template label"), + hoverHelp => $i18n->get("inbox style template hoverHelp") + ); + $f->template( + name => "inboxLayoutTempalteId", + value => $self->getLayoutTemplateId, + namespace => "Account/Layout", + label => $i18n->get("inbox layout template label"), + hoverHelp => $i18n->get("inbox layout template hoverHelp") + ); + $f->template( + name => "inboxViewTemplateId", + value => $self->getViewTemplateId, + namespace => "Account/Inbox/View", + label => $i18n->get("inbox view template label"), + hoverHelp => $i18n->get("inbox view template hoverHelp") + ); + $f->template( + name => "inboxViewMessageTemplateId", + value => $self->getViewMessageTemplateId, + namespace => "Account/Inbox/ViewMessage", + label => $i18n->get("inbox view message template label"), + hoverHelp => $i18n->get("inbox view message template hoverHelp") + ); + $f->template( + name => "inboxSendMessageTemplateId", + value => $self->getSendMessageTemplateId, + namespace => "Account/Inbox/SendMessage", + label => $i18n->get("inbox send message template label"), + hoverHelp => $i18n->get("inbox send message template hoverHelp") + ); + $f->template( + name => "inboxMessageConfirmationTemplateId", + value => $self->getMessageConfirmTemplateId, + namespace => "Account/Inbox/Confirm", + label => $i18n->get("inbox message confirm template label"), + hoverHelp => $i18n->get("inbox message confirm template hoverHelp") + ); + $f->template( + name => "inboxErrorTemplateId", + value => $self->getInboxErrorTemplateId, + namespace => "Account/Inbox/Error", + label => $i18n->get("inbox error message template label"), + hoverHelp => $i18n->get("inbox error message template hoverHelp") + ); + $f->template( + name => "inboxManageInvitationsTemplateId", + value => $self->getManageInvitationsTemplateId, + namespace => "Account/Inbox/ManageInvitations", + label => $i18n->get("inbox manage invitations template label"), + hoverHelp => $i18n->get("inbox manage invitations template hoverHelp") + ); + $f->template( + name => "inboxInvitationErrorTemplateId", + value => $self->getInvitationErrorTemplateId, + namespace => "Account/Inbox/Error", + label => $i18n->get("invitation error message template label"), + hoverHelp => $i18n->get("invitation error message template hoverHelp") + ); return $f->printRowsOnly; } @@ -61,7 +163,50 @@ sub editUserSettingsForm { =cut -sub editUserSettingsFormSave { +sub editSettingsFormSave { + my $self = shift; + my $session = $self->session; + my $setting = $session->setting; + my $form = $session->form; + + #Messages Settings + $setting->set("inboxStyleTemplateId", $form->process("inboxStyleTemplateId","template")); + $setting->set("inboxLayoutTempalteId", $form->process("inboxLayoutTempalteId","template")); + $setting->set("inboxViewTemplateId", $form->process("inboxViewTemplateId","template")); + $session->set("inboxViewMessageTemplateId",$form->process("inboxViewMessageTemplateId","template")); + $session->set("inboxSendMessageTemplateId",$form->process("inboxSendMessageTemplateId","template")); + $session->set("inboxMessageConfirmationTemplateId",$form->process("inboxMessageConfirmationTemplateId","template")); + $session->set("inboxErrorTemplateId",$form->process("inboxErrorTemplateId","template")); + #Invitations Settings + $session->set("inboxManageInvitationsTemplateId",$form->process("inboxManageInvitationsTemplateId","template")); + $session->set("inboxInvitationErrorTemplateId",$form->process("inboxInvitationErrorTemplateId","template")); +} + +#------------------------------------------------------------------- + +=head2 getInboxErrorTemplateId ( ) + +This method returns the template ID for inbox errors. + +=cut + +sub getInboxErrorTemplateId { + my $self = shift; + return $self->session->setting->get("inboxErrorTemplateId") || "ErEzulFiEKDkaCDVmxUavw"; +} + + +#------------------------------------------------------------------- + +=head2 getInvitationErrorTemplateId ( ) + +This method returns the template ID for invitation errors. + +=cut + +sub getInvitationErrorTemplateId { + my $self = shift; + return $self->session->setting->get("inboxInvitationErrorTemplateId") || "5A8Hd9zXvByTDy4x-H28qw"; } #------------------------------------------------------------------- @@ -77,6 +222,45 @@ sub getLayoutTemplateId { return $self->session->setting->get("inboxLayoutTempalteId") || $self->SUPER::getLayoutTemplateId; } +#------------------------------------------------------------------- + +=head2 getManageInvitationsTemplateId ( ) + +This method returns the template ID for the invitations manage screen. + +=cut + +sub getManageInvitationsTemplateId { + my $self = shift; + return $self->session->setting->get("inboxManageInvitationsTemplateId") || "1Q4Je3hKCJzeo0ZBB5YB8g"; +} + +#------------------------------------------------------------------- + +=head2 getMessageConfirmTemplateId ( ) + +This method returns the template ID for message confirmations. + +=cut + +sub getMessageConfirmTemplateId { + my $self = shift; + return $self->session->setting->get("inboxMessageConfirmationTemplateId") || "DUoxlTBXhVS-Zl3CFDpt9g"; +} + + +#------------------------------------------------------------------- + +=head2 getSendMessageTemplateId ( ) + +This method returns the template ID for the send message view. + +=cut + +sub getSendMessageTemplateId { + my $self = shift; + return $self->session->setting->get("inboxSendMessageTemplateId") || "6uQEULvXFgCYlRWnYzZsuA"; +} #------------------------------------------------------------------- @@ -93,6 +277,39 @@ sub getStyleTemplateId { #------------------------------------------------------------------- +=head2 getUserProfileUrl ( userId ) + +This method stores a reference of user profile URLs to prevent us from having to instantiate +the same users over and over as the nature of an inbox is to have multiple messages from the same user. + +=cut + +sub getUserProfileUrl { + my $self = shift; + my $userId = shift; + + + unless ($self->store->{$userId}) { + $self->store->{$userId} = WebGUI::User->new($self->session,$userId)->getProfileUrl; + } + return $self->store->{$userId}; +} + +#------------------------------------------------------------------- + +=head2 getViewMessageTemplateId ( ) + +This method returns the id for the view message template. + +=cut + +sub getViewMessageTemplateId { + my $self = shift; + return $self->session->setting->get("inboxViewMessageTemplateId") || "0n4HtbXaWa_XJHkFjetnLQs"; +} + +#------------------------------------------------------------------- + =head2 getViewTemplateId ( ) This method returns the template ID for the main view. @@ -101,9 +318,356 @@ This method returns the template ID for the main view. sub getViewTemplateId { my $self = shift; - return $self->session->setting->get("inboxViewTemplateId") || "defaultAssetId"; + return $self->session->setting->get("inboxViewTemplateId") || "c8xrwVuu5QE0XtF9DiVzLw"; } +#------------------------------------------------------------------- + +=head2 www_deleteMessage ( ) + +Deletes a single messages passed in + +=cut + +sub www_deleteMessage { + my $self = shift; + my $session = $self->session; + + my $messageId = $session->form->get("messageId"); + my $inbox = WebGUI::Inbox->new($session); + my $message = $inbox->getMessage($messageId); + + if (!(defined $message) || !$inbox->canRead($message)) { + #View will handle displaying these errors + return $self->www_viewMessage; + } + + #Get the next message to display + my $displayMessage = $inbox->getNextMessage($message); + unless (defined $displayMessage) { + #No more messages - try to get the previous message + $displayMessage = $inbox->getPreviousMessage($message); + unless (defined $displayMessage) { + #This is the last message in the inbox - delete it and return to inbox + $message->delete; + return $self->www_view(); + } + } + $message->delete; + + return $self->www_viewMessage($displayMessage->getId); +} + +#------------------------------------------------------------------- + +=head2 www_deleteMessages ( ) + +Deletes a list of messages selected for the current user + +=cut + +sub www_deleteMessages { + my $self = shift; + my $session = $self->session; + + my @messages = $session->form->process("message","checkList"); + + foreach my $messageId (@messages) { + my $message = WebGUI::Inbox::Message->new($session, $messageId); + $message->delete; + } + + return $self->www_view(); +} + +#------------------------------------------------------------------- + +=head2 www_manageInvitations ( ) + +The page on which users can manage their friends requests + +=cut + +sub www_manageInvitations { + my $self = shift; + my $session = $self->session; + my $user = $session->user; + + my $var = {}; + + #Add common template variable for displaying the inbox + my $inbox = WebGUI::Inbox->new($session); + $self->appendCommonVars($var,$inbox); + + return $self->processTemplate($var,$self->getManageInvitationsTemplateId); +} + +#------------------------------------------------------------------- + +=head2 www_sendMessage ( ) + +The page on which users send or reply to messages + +=cut + +sub www_sendMessage { + my $self = shift; + my $session = $self->session; + my $form = $session->form; + my $fromUser = $session->user; + my $displayError = shift; + my $toUser = undef; + my $var = {}; + + #Add any error passed in to be displayed if the form reloads + $var->{'message_display_error'} = $displayError; + + #Add common template variable for displaying the inbox + my $inbox = WebGUI::Inbox->new($session); + $self->appendCommonVars($var,$inbox); + + my $messageId = $form->get("messageId"); + my $userId = $form->get("userId"); + my $pageUrl = $session->url->page; + my $backUrl = $session->env->get("HTTP_REFERER") || $var->{'view_inbox_url'}; + my $errorMsg = ""; + + if($messageId) { + #This is a reply to a message - automate who the user is + my $message = $inbox->getMessage($messageId); + + #Handle Errors + if (!(defined $message)) { + #Message doesn't exist + my $i18n = WebGUI::International->new($session,'Account_Inbox'); + $errorMsg = $i18n->get("message does not exist"); + } + elsif (!$inbox->canRead($message)) { + #User trying to reply to message that they have not been sent. + my $i18n = WebGUI::International->new($session,'Account_Inbox'); + $errorMsg = $i18n->get("no reply error"); + } + elsif($message->get("status") eq "completed" || $message->get("status") eq "pending") { + #User trying to reply to system message + my $i18n = WebGUI::International->new($session,'Account_Inbox'); + $errorMsg = $i18n->get("system message error"); + } + if($errorMsg) { + return $self->showError($var,$errorMsg,$backUrl,$self->getInboxErrorTemplateId); + } + + #Otherwise you should be able to reply to anyone who sent you a message + $toUser = WebGUI::User->new($session,$message->get("sentBy")); + $var->{'isReply' } = "true"; + $var->{'message_to' } = $toUser->getWholeName; + $var->{'message_subject'} = $message->get("subject"); + } + elsif($userId) { + #This is a private message to a user - check user private message settings + + #Handle Errors + $toUser = WebGUI::User->new($session,$userId); + if($toUser->isVisitor || !$toUser->acceptsPrivateMessages($fromUser->userId)) { + #Trying to send messages to the visitor or a user that doesn't exist + my $i18n = WebGUI::International->new($session,'Account_Inbox'); + $errorMsg = $i18n->get("blocked error"); + } + elsif($toUser->userId eq $fromUser->userId) { + #Trying to send a message to yourself + my $i18n = WebGUI::International->new($session,'Account_Inbox'); + $errorMsg = $i18n->get("no self error"); + } + if($errorMsg) { + return $self->showError($var,$errorMsg,$backUrl,$self->getInboxErrorTemplateId); + } + + $var->{'isPrivateMessage'} = "true"; + $var->{'message_to' } = $toUser->getWholeName; + } + else { + #This is a new message + $var->{'isNew' } = "true"; + + my $friends = $fromUser->friends->getUserList; + my @checkedFriends = (); + my @friendsChecked = $form->process("friend","checkList"); + my $activeFriendCount = 0; + #Append this users friends to the template + my @friendsLoop = (); + foreach my $friendId (keys %{$friends}) { + my $friend = WebGUI::User->new($session,$friendId); + #This friend has private messages turned off + my $disabled = "disabled"; + if($friend->acceptsPrivateMessages($fromUser->userId)) { + $disabled = ""; + $activeFriendCount++; + } + my $fname = $friend->profileField("firstName"); + my $lname = $friend->profileField("lastName"); + my $wholeName = ""; + $wholeName = $fname." ".$lname if($fname && $lname); + + my $isChecked = WebGUI::Utility::isIn($friendId,@friendsChecked); + my $friendHash = { + 'friend_id' => $friendId, + 'friend_name' => $friends->{$friendId}, + 'friend_wholeName' => $wholeName, + }; + + push(@checkedFriends,$friendHash) if($isChecked); + + $friendHash->{'friend_checkbox'} = WebGUI::Form::checkbox($session,{ + name => "friend", + value => $friendId, + checked => $isChecked, + extras => q{id="friend_}.$friendId.qq{_id" $disabled}, + }); + + push (@friendsLoop, $friendHash); + } + + #You can't send new messages if you don't have any friends to send to + unless($activeFriendCount) { + my $i18n = WebGUI::International->new($session,'Account_Inbox'); + $errorMsg = $i18n->get("no friends error"); + return $self->showError($var,$errorMsg,$backUrl,$self->getInboxErrorTemplateId); + } + + $var->{'friends_loop' } = \@friendsLoop; + $var->{'checked_fiends_loop'} = \@checkedFriends; + } + + $var->{'message_from' } = $fromUser->getWholeName; + + my $subject = $form->get("subject"); + if($subject eq "" && $messageId) { + $subject = "Re: ".$var->{'message_subject'}; + } + + $var->{'form_subject' } = WebGUI::Form::text($session, { + name => "subject", + value => $subject, + extras => q{ class="inbox_subject" } + }); + + $var->{'message_body' } = $form->get('message'); + + $var->{'form_message_text'} = WebGUI::Form::textarea($session, { + name =>"message", + value =>$var->{'message_body'} || "", + }); + + $var->{'form_message_rich'} = WebGUI::Form::HTMLArea($session, { + name => "message", + value => $var->{'message_body'} || "", + width => "600", + }); + + $var->{'form_header' } = WebGUI::Form::formHeader($session,{ + action => $self->getUrl("module=inbox;do=sendMessageSave;messageId=$messageId;userId=$userId"), + extras => q{name="messageForm"} + }); + + $var->{'submit_button' } = WebGUI::Form::submit($session,{}); + $var->{'form_footer' } = WebGUI::Form::formFooter($session, {}); + $var->{'back_url' } = $backUrl; + + return $self->processTemplate($var,$self->getSendMessageTemplateId); +} + +#------------------------------------------------------------------- + +=head2 www_sendMessageSave ( ) + +Sends the message created by the user + +=cut + +sub www_sendMessageSave { + my $self = shift; + my $session = $self->session; + my $form = $session->form; + my $fromUser = $session->user; + my $var = {}; + my $errorMsg = ""; + my @toUsers = (); + + #Add common template variable for displaying the inbox + my $inbox = WebGUI::Inbox->new($session); + + my $messageId = $form->get("messageId"); + my $userId = $form->get("userId"); + my @friends = $form->get("friend","checkList"); + push (@friends, $userId) if ($userId); + + my $hasError = 0; + + my $subject = $form->get("subject"); + my $message = $form->get("message"); + + #Check for hacker errors / set who the message is going to + if($messageId) { + #This is a reply to a message - automate who the user is + my $message = $inbox->getMessage($messageId); + #Handle Errors + if (!(defined $message) + || !$inbox->canRead($message) + || $message->get("status") eq "completed" + || $message->get("status") eq "pending") { + $hasError = 1; + } + push(@toUsers,$message->get("sentBy")); + $message->setStatus("replied"); + } + elsif(scalar(@friends)) { + #This is a private message to a user - check user private message settings + foreach my $userId (@friends) { + my $toUser = WebGUI::User->new($session,$userId); + if($toUser->isVisitor + || !$toUser->acceptsPrivateMessages($fromUser->userId) + || $toUser->userId eq $fromUser->userId) { + $hasError = 1; + } + push(@toUsers,$userId); + } + } + + #Check for client errors + if($subject eq "") { + my $i18n = WebGUI::International->new($session,'Account_Inbox'); + $errorMsg = $i18n->get("no subject error"); + $hasError = 1; + } + elsif($message eq "") { + my $i18n = WebGUI::International->new($session,'Account_Inbox'); + $errorMsg = $i18n->get("no message error"); + $hasError = 1; + } + elsif(scalar(@toUsers) == 0) { + my $i18n = WebGUI::International->new($session,'Account_Inbox'); + $errorMsg = $i18n->get("no user error"); + $hasError = 1; + } + + #Let sendMessage deal with displaying errors + return $self->www_sendMessage($errorMsg) if $hasError; + + foreach my $uid (@toUsers) { + $inbox->addMessage({ + message => $message, + subject => $subject, + userId => $uid, + status => 'unread', + sentBy => $fromUser->userId + }); + } + + $self->appendCommonVars($var,$inbox); + + return $self->processTemplate($var,$self->getMessageConfirmTemplateId); +} + + #------------------------------------------------------------------- =head2 www_view ( ) @@ -115,10 +679,189 @@ The main view page for editing the user's profile. sub www_view { my $self = shift; my $session = $self->session; + my $user = $session->user; my $var = {}; + + #Deal with sort order + my $sortBy = $session->form->get("sortBy") || undef; + my $sort_url = ($sortBy)?";sortBy=$sortBy":""; + + #Deal with sort direction + my $sortDir = $session->form->get("sortDir") || "desc"; + my $sortDir_url = ";sortDir=".(($sortDir eq "desc")?"asc":"desc"); + #Deal with rows per page + my $rpp = $session->form->get("rpp") || 25; + my $rpp_url = ";rpp=$rpp"; + + #Cache the base url + my $inboxUrl = $self->getUrl; + + #Create sortBy headers + $var->{'subject_url' } = $inboxUrl.";sortBy=subject".$sortDir_url.$rpp_url; + $var->{'status_url' } = $inboxUrl.";sortBy=status".$sortDir_url.$rpp_url; + $var->{'from_url' } = $inboxUrl.";sortBy=sentBy".$sortDir_url.$rpp_url; + $var->{'dateStamp_url' } = $inboxUrl.";sortBy=dateStamp".$sortDir_url.$rpp_url; + $var->{'rpp_url' } = $inboxUrl.$sort_url.";sortDir=".$sortDir; + + #Create the paginator + my $inbox = WebGUI::Inbox->new($session); + my $p = $inbox->getMessagesPaginator($session->user,{ + sortBy => $sortBy, + sortDir => $sortDir, + baseUrl => $inboxUrl.$sort_url.";sortDir=".$sortDir.$rpp_url, + paginateAfter => $rpp + }); + + #Export page to template + my @msg = (); + foreach my $row ( @{$p->getPageData} ) { + my $message = $inbox->getMessage( $row->{messageId} ); + #next if($message->get('status') eq 'deleted'); + + my $hash = {}; + $hash->{'message_id' } = $message->getId; + $hash->{'message_url' } = $self->getUrl("module=inbox;do=viewMessage;messageId=".$message->getId); + $hash->{'subject' } = $message->get("subject"); + $hash->{'status_class' } = $message->get("status"); + $hash->{'status' } = $message->getStatus; + $hash->{'isRead' } = $message->isRead; + $hash->{'isReplied' } = $hash->{'status_class'} eq "replied"; + $hash->{'isPending' } = $hash->{'status_class'} eq "pending"; + $hash->{'isCompleted' } = $hash->{'status_class'} eq "completed"; + $hash->{'from_id' } = $message->get("sentBy"); + $hash->{'from_url' } = $self->getUserProfileUrl($hash->{'from_id'}); #Get the profile url of this user which may be cached. + $hash->{'from' } = $row->{'fullName'}; + $hash->{'dateStamp' } = $message->get("dateStamp"); + $hash->{'dateStamp_formatted'} = $session->datetime->epochToHuman($hash->{'dateStamp'}); + $hash->{'inbox_form_delete' } = WebGUI::Form::checkbox($session,{ + name => "message", + value => $message->getId + }); + push(@msg,$hash); + } + my $msgCount = $p->getRowCount; + + $var->{'message_loop' } = \@msg; + $var->{'has_messages' } = $msgCount > 0; + $var->{'message_total' } = $msgCount; + $var->{'new_message_url' } = $self->getUrl("module=inbox;do=sendMessage"); + $var->{'canSendMessages' } = $user->hasFriends; + + $var->{'inbox_form_start' } = WebGUI::Form::formHeader($session,{ + action => $self->getUrl("module=inbox;do=deleteMessages") + }); + $var->{'inbox_form_end' } = WebGUI::Form::formFooter($session); + + tie my %rpps, "Tie::IxHash"; + %rpps = (25 => "25", 50 => "50", 100=>"100"); + $var->{'message_rpp' } = WebGUI::Form::selectBox($session,{ + name =>"rpp", + options => \%rpps, + value => $session->form->get("rpp") || 25, + extras => q{onchange="location.href='}.$var->{'rpp_url'}.q{;rpp='+this.options[this.selectedIndex].value"} + }); + + #Append common vars + $self->appendCommonVars($var,$inbox); + #Append pagination vars + $p->appendTemplateVars($var); return $self->processTemplate($var,$self->getViewTemplateId); } +#------------------------------------------------------------------- + +=head2 www_viewMessage ( ) + +The page on which users view their messages + +=cut + +sub www_viewMessage { + my $self = shift; + my $session = $self->session; + my $user = $session->user; + + my $var = {}; + my $messageId = shift || $session->form->get("messageId"); + my $errorMsg = shift; + + my $inbox = WebGUI::Inbox->new($session); + my $message = $inbox->getMessage($messageId); + + #Add common template variable for displaying the inbox + $self->appendCommonVars($var,$inbox); + + #Handler Errors + if (!(defined $message)) { + my $i18n = WebGUI::International->new($session,'Account_Inbox'); + $errorMsg = $i18n->get("message does not exist"); + } + elsif (!$inbox->canRead($message)) { + my $i18n = WebGUI::International->new($session,'Account_Inbox'); + $errorMsg = $i18n->get("no access"); + } + + if($errorMsg) { + my $backUrl = $var->{'view_inbox_url'}; + return $self->showError($var,$errorMsg,$backUrl,$self->getInboxErrorTemplateId); + } + + $message->setStatus("read") unless ($message->isRead); + + $var->{'message_id' } = $messageId; + $var->{'message_subject' } = $message->get("subject"); + $var->{'message_dateStamp' } = $message->get("dateStamp"); + $var->{'message_dateStemp_human'} = $session->datetime->epochToHuman($var->{'message_dateStamp'}); + $var->{'message_status' } = $message->getStatus; + $var->{'message_body' } = $message->get("message"); + + unless ($var->{'message_body'} =~ /\{'message_body'} =~ s/(http\S*)/\$1\<\/a\>/g; + } + unless ($var->{'message_body'} =~ /\
{'message_body'} =~ /\
{'message_body'} =~ /\

{'message_body'} =~ s/\n/\
\n/g; + } + + #Get the user the message was sent by + my $sentBy = $message->get("sentBy"); + my $from = WebGUI::User->new($session,$sentBy); + my $sentByVisitor = 0; + if ($from->isVisitor) { + $sentByVisitor = 1; + $from = WebGUI::User->new($session,3); + } + $var->{'message_from_id' } = $from->userId; + $var->{'message_from' } = $from->getWholeName; + + #Build the action URLs + $var->{'delete_url' } = $self->getUrl("module=inbox;do=deleteMessage;messageId=".$messageId); + + my $status = $message->get("status"); + if($sentBy ne $user->userId + && !$sentByVisitor + && $status ne "pending" + && $status ne "completed" ) { + $var->{'canReply' } = "true"; + $var->{'reply_url'} = $self->getUrl("module=inbox;do=sendMessage;messageId=".$messageId); + } + + my $nextMessage = $inbox->getNextMessage($message); + if( defined $nextMessage ) { + $var->{'hasNext' } = "true"; + $var->{'next_message_url'} = $self->getUrl("module=inbox;do=viewMessage;messageId=".$nextMessage->getId); + } + + my $prevMessage = $inbox->getPreviousMessage($message); + if(defined $prevMessage) { + $var->{'hasPrevious' } = "true"; + $var->{'prev_message_url'} = $self->getUrl("module=inbox;do=viewMessage;messageId=".$prevMessage->getId); + } + + return $self->processTemplate($var,$self->getViewMessageTemplateId); +} + 1; diff --git a/lib/WebGUI/Account/Profile.pm b/lib/WebGUI/Account/Profile.pm index 410167616..6adbe4854 100644 --- a/lib/WebGUI/Account/Profile.pm +++ b/lib/WebGUI/Account/Profile.pm @@ -5,6 +5,8 @@ use strict; use WebGUI::Exception; use WebGUI::International; use WebGUI::Pluggable; +use WebGUI::ProfileCategory; +use WebGUI::ProfileField; use WebGUI::Utility; use base qw/WebGUI::Account/; @@ -26,6 +28,31 @@ These subroutines are available from this package: =cut +#------------------------------------------------------------------- + +=head2 appendCommonVars ( var ) + + Appends common template variables that all inbox templates use + +=head3 var + + The hash reference to append template variables to + +=cut + +sub appendCommonVars { + my $self = shift; + my $var = shift; + my $session = $self->session; + my $user = $session->user; + my $pageUrl = $session->url->page; + + $var->{'user_full_name' } = $user->getWholeName; + $var->{'user_member_since' } = $user->dateCreated; + $var->{'view_profile_url' } = $user->getProfileUrl($pageUrl); + $var->{'edit_profile_url' } = $self->getUrl("module=profile;do=edit"); + $var->{'back_url' } = $session->env->get("HTTP_REFERER") || $var->{'view_profile_url'} +} #------------------------------------------------------------------- @@ -35,7 +62,7 @@ These subroutines are available from this package: =cut -sub editUserSettingsForm { +sub editSettingsForm { my $self = shift; my $session = $self->session; my $setting = $session->setting; @@ -50,41 +77,121 @@ sub editUserSettingsForm { hoverHelp => $i18n->get("profile style template hoverHelp") ); $f->template( - name => "profileLayoutTempalteId", + name => "profileLayoutTemplateId", value => $self->getLayoutTemplateId, namespace => "Account/Layout", label => $i18n->get("profile layout template label"), hoverHelp => $i18n->get("profile layout template hoverHelp") ); + $f->template( + name => "profileEditLayoutTemplateId", + value => $self->getEditLayoutTemplateId, + namespace => "Account/Layout", + label => $i18n->get("profile edit layout template label"), + hoverHelp => $i18n->get("profile edit layout template hoverHelp") + ); $f->template( + name => "profileEditTemplateId", + value => $self->getEditTemplateId, + namespace => "Account/Profile/Edit", + label => $i18n->get("profile edit template label"), + hoverHelp => $i18n->get("profile edit template hoverHelp") + ); + $f->template( name => "profileViewTemplateId", value => $self->getViewTemplateId, namespace => "Account/Profile/View", label => $i18n->get("profile view template label"), hoverHelp => $i18n->get("profile view template hoverHelp") ); - $f->template( - name => "profileEditTemplateId", - value => $setting->get("profileEditTemplateId"), - namespace => "Account/Profile/Edit", - label => $i18n->get("profile edit template label"), - hoverHelp => $i18n->get("profile edit template hoverHelp") - ); return $f->printRowsOnly; } + #------------------------------------------------------------------- -=head2 getDisplayTemplateId ( ) +=head2 editSettingsFormSave ( ) + + Creates form elements for user settings page custom to this account module + +=cut + +sub editSettingsFormSave { + my $self = shift; + my $session = $self->session; + my $setting = $session->setting; + my $form = $session->form; + + $setting->set("profileStyleTemplateId", $form->process("profileStyleTemplateId","template")); + $setting->set("profileLayoutTemplateId", $form->process("profileLayoutTemplateId","template")); + $setting->set("profileDisplayLayoutTemplateId", $form->process("profileDisplayLayoutTemplateId","template")); + $setting->set("profileEditTemplateId", $form->process("profileEditTemplateId","template")); + $setting->set("profileViewTempalteId", $form->process("profileViewTemplateId","template")); + +} + +#------------------------------------------------------------------- + +=head2 getExtrasStyle ( field, fieldErrors, fieldValue ) + +This method returns the proper field to display for required fields. + +=head3 field + +field to check + +=head3 fieldErrors + +errors returned as a result of validation (see $self->validateProfileFields) + +=head3 fieldValue + +Value of the field to use when returning the style + +=cut + +sub getExtrasStyle { + my $self = shift; + my $field = shift; + my $fieldErrors = shift; + my $fieldValue = shift; + + my $requiredStyleOff = q{class="profilefield_required_off"}; + my $requiredStyle = q{class="profilefield_required"}; + my $errorStyle = q{class="profilefield_error"}; #Required Field Not Filled In and Error Returend + + return $errorStyle if(WebGUI::Utility::isIn($field->getId,@{$fieldErrors})); + return "" unless ($field->isRequired); + return $requiredStyle unless($self->session->user->profileField($field->getId) || $fieldValue); + return $requiredStyleOff; +} + + +#------------------------------------------------------------------- + +=head2 getDisplayLayoutTemplateId ( ) This method returns the template ID for the account layout. =cut -sub getDisplayTemplateId { +sub getEditLayoutTemplateId { + my $self = shift; + return $self->session->setting->get("profileEditLayoutTemplateId") || "FJbUTvZ2nUTn65LpW6gjsA"; +} + +#------------------------------------------------------------------- + +=head2 getEditTemplateId ( ) + +This method returns the template ID for the edit profile page. + +=cut + +sub getEditTemplateId { my $self = shift; - return $self->session->setting->get("profileDisplayTempalteId") || "defaultAssetId"; + return $self->session->setting->get("profileEditTemplateId") || "75CmQgpcCSkdsL-oawdn3Q"; } #------------------------------------------------------------------- @@ -96,8 +203,13 @@ This method returns the template ID for the account layout. =cut sub getLayoutTemplateId { - my $self = shift; - return $self->session->setting->get("profileLayoutTempalteId") || $self->SUPER::getLayoutTemplateId; + my $self = shift; + my $session = $self->session; + my $method = $session->form->get("do"); + my $uid = $session->form->get("uid"); + + return $self->getEditLayoutTemplateId if($method eq "edit" || $uid eq ""); + return $session->setting->get("profileLayoutTemplateId") || $self->SUPER::getLayoutTemplateId; } #------------------------------------------------------------------- @@ -117,30 +229,342 @@ sub getStyleTemplateId { =head2 getViewTemplateId ( ) -This method returns the template ID for the main view. +This method returns the template ID for the view profile page. =cut sub getViewTemplateId { my $self = shift; - return $self->session->setting->get("profileViewTemplateId") || "75CmQgpcCSkdsL-oawdn3Q"; + return $self->session->setting->get("profileViewTemplateId") || "2CS-BErrjMmESOtGT90qOg"; +} + +#------------------------------------------------------------------- + +=head2 saveProfileFields ( session, user, profile ) + +Saves profile data to a user's profile. Does not validate any of the data. + +=head3 session + +WebGUI session object + +=head3 user + +User object. Profile data will be placed in this user's profile. + +=head3 profile + +Hash ref of profile data to save. + +=cut + +sub saveProfileFields { + my $class = shift; + my $session = shift; + my $u = shift; + my $profile = shift; + + foreach my $fieldName (keys %{$profile}) { + $u->profileField($fieldName,${$profile}{$fieldName}); + } +} + +#------------------------------------------------------------------- + +=head2 validateProfileFields ( session, fields ) + +Class method which validates profile data from the session form variables. Returns an data structure which contains the following + +{ + profile => Hash reference containing all of the profile fields and their values + errors => Array reference of error messages to be displayed + errorCategory => Category in which the first error was thrown + warnings => Array reference of warnings to be displayed + errorFields => Array reference of the fieldIds that threw an error + warningFields => Array reference of the fieldIds that threw a warning +} + +=head3 session + +WebGUI session object + +=head3 fields + +An array reference of profile fields to validate. + +=cut + +sub validateProfileFields { + my $class = shift; + my $session = shift; + my $fields = shift; + + my $i18n = WebGUI::International->new($session, 'Account_Profile'); + + my $data = {}; + my $errors = []; + my $warnings = []; + my $errorCat = undef; + my $errorFields = []; + my $warnFields = []; + + foreach my $field (@{$fields}) { + my $fieldId = $field->getId; + my $fieldLabel = $field->getLabel; + my $fieldValue = $field->formProcess; + my $isValid = $field->isValid($fieldValue); + + $data->{$fieldId} = (ref $fieldValue eq "ARRAY") ? $fieldValue->[0] : $fieldValue; + + if(!$isValid) { + $errorCat = $field->get("profileCategoryId") unless (defined $errorCat); + push (@{$errors}, sprintf($i18n->get("required error"),$fieldLabel)); + push(@{$errorFields},$fieldId); + } + #The language field is special and must be always be valid or WebGUI will croak + elsif($fieldId eq "language" && !(exists $i18n->getLanguages()->{$data->{$fieldId}})) { + $errorCat = $field->get("profileCategoryId") unless (defined $errorCat); + $session->log->warn("language $fieldValue does not exist"); + push (@{$errors}, sprintf($i18n->get("language not installed error"),$data->{$fieldId})); + push(@{$errorFields},$fieldId); + } + #Duplicate emails throw warnings + elsif($fieldId eq "email" && $field->isDuplicate($fieldValue)) { + $errorCat = $field->get("profileCategoryId") unless (defined $errorCat); + push (@{$warnings},$i18n->get("email already in use error")); + push(@{$warnFields},$fieldId); + } + } + + return { + profile => $data, + errors => $errors, + warnings => $warnings, + errorCategory => $errorCat, + errorFields => $errorFields, + warningFields => $warnFields, + }; +} + +#------------------------------------------------------------------- + +=head2 www_edit ( ) + +The edit page for the user's profile. + +=cut + +sub www_edit { + my $self = shift; + my $errors = shift || {}; + my $session = $self->session; + my $user = $session->user; + my $selected = $errors->{errorCategory} || $session->form->get("selected"); #Allow users to template tabs or other category dividers + my $var = {}; + + my $active = 0; #Whether or not a category is selected + my $counter = 1; #Count the number of categories being displayed + my $hasErrors = scalar(keys %{$errors}); + + my @errorFields = (); + @errorFields = (@{$errors->{errorFields}},@{$errors->{warningFields}}) if($hasErrors); + + my @categories = (); + foreach my $category (@{WebGUI::ProfileCategory->getCategories($session)}) { + next unless $category->isEditable; + my @fields = (); + foreach my $field (@{$category->getFields}) { + next unless ($field->isEditable); + next if $field->getId =~ m/contentPositions/; #This protects the contentPosition fields + my $fieldId = $field->getId; + my $fieldLabel = $field->getLabel; + my $fieldForm = $field->formField({ extras=>$self->getExtrasStyle($field,\@errorFields,$user->profileField($fieldId)) }); + my $fieldSubtext = $field->isRequired ? "*" : undef; + my $fieldExtras = $field->getExtras; + #Create a seperate template var for each field + $var->{'profile_field_'.$fieldId.'_form' } = $fieldForm; + $var->{'profile_field_'.$fieldId.'_label' } = $fieldLabel; + $var->{'profile_field_'.$fieldId.'_subtext'} = $fieldSubtext; + $var->{'profile_field_'.$fieldId.'_extras' } = $fieldExtras; + + push(@fields, { + 'profile_field_id' => $fieldId, + 'profile_field_form' => $fieldForm, + 'profile_field_label' => $fieldLabel, + 'profile_field_subtext' => $field->isRequired ? "*" : undef, + 'profile_field_extras' => $field->getExtras, + }); + } + my $categoryId = $category->getId; + my $categoryLabel = $category->getLabel; + my $shortCategoryLabel = $category->getShortLabel; + my $isActive = $categoryId eq $selected; + my $categoryIndex = $counter++; + + $var->{'profile_category_'.$categoryId."_isActive" } = $isActive; + $var->{'profile_category_'.$categoryId."_label" } = $categoryLabel; + $var->{'profile_category_'.$categoryId."_shortLabel"} = $shortCategoryLabel; + $var->{'profile_category_'.$categoryId."_fields" } = \@fields; + $var->{'profile_category_'.$categoryId."_index" } = $categoryIndex; + + push(@categories, { + 'profile_category_id' => $categoryId, + 'profile_category_isActive' => $isActive, + 'profile_category_is_'.$categoryId => "true", #Test so users can tell what category they are at in the loop + 'profile_category_label' => $categoryLabel, + 'profile_category_shortLabel' => $shortCategoryLabel, + 'profile_category_index' => $categoryIndex, + 'profile_fields_loop' => \@fields, + }); + #This value will determine whether or not a valid category is active or not + $active ||= $isActive; + } + + #If not category is selected, set the first category as the active one + $categories[0]->{profile_category_isActive} = 1 unless($active); + + $var->{'profile_category_loop'} = \@categories; + + $var->{'profile_form_submit' } = WebGUI::Form::submit($session,{}); + $var->{'profile_form_header' } = WebGUI::Form::formHeader($session,{ + action => $self->getUrl("module=profile;do=editSave") + }); + $var->{'profile_form_footer' } = WebGUI::Form::formFooter($session); + + $var->{'profile_errors' } = []; + map{ push(@{$var->{'profile_errors'}},{ error_message => $_ }) } @{$errors->{errors}} if($hasErrors); + + $self->appendCommonVars($var); + + return $self->processTemplate($var,$self->getEditTemplateId); +} + + +#------------------------------------------------------------------- + +=head2 www_editSave ( ) + +The page which saves the user's profile and returns them to their profile view. + +=cut + +sub www_editSave { + my $self = shift; + my $session = $self->session; + + my $fields = WebGUI::ProfileField->getEditableFields($session); + my $retHash = $self->validateProfileFields($session,$fields); + push (@{$retHash->{errors}},@{$retHash->{warnings}}); + + unless(scalar(@{$retHash->{errors}})) { + foreach my $fieldName (keys %{$retHash->{profile}}) { + $session->user->profileField($fieldName,$retHash->{profile}->{$fieldName}); + } + } + + return $self->www_edit($retHash); } #------------------------------------------------------------------- =head2 www_view ( ) -The main view page for the user's profile. +The display page of the . =cut sub www_view { - my $self = shift; - my $session = $self->session; - my $var = {}; + my $self = shift; + my $session = $self->session; + my $i18n = WebGUI::International->new($session, 'Account_Profile'); + my $var = {}; + my $uid = $session->form->get("uid"); + my $selected = $session->form->get("selected"); #Allow users to template tabs or other category dividers - return $self->processTemplate($var,$session->setting->get("profileViewTemplateId")); + my $active = 0; #Whether or not a category is selected + my $counter = 1; #Count the number of categories being displayed + + #Ensure uid is passed in if they want to view a profile. This controls the tab state. + return $self->www_edit unless ($uid); + + my $user = WebGUI::User->new($session,$uid); + + #Check user privileges + #return $session->style->userStyle($vars->{displayTitle}.'. '.$i18n->get(862)) if($u->profileField("publicProfile") < 1 && ($session->user->userId ne $session->form->process("uid") || $session->user->isAdmin)); + #return $session->privilege->insufficient() if(!$session->user->isRegistered); + + if($user->isVisitor) { + $var->{'restricted' } = "true"; + $var->{'error_message'} = $i18n->get("visitor profile restricted"); + } + + my @categories = (); + foreach my $category (@{WebGUI::ProfileCategory->getCategories($session)}) { + next unless $category->isViewable; + my @fields = (); + foreach my $field (@{$category->getFields}) { + next unless ($field->isViewable); + next if $field->getId =~ m/contentPositions/; #This protects the contentPosition fields + my $fieldId = $field->getId; + my $fieldLabel = $field->getLabel; + my $fieldValue = $field->formField(undef,2,$user); + my $fieldRaw = $user->profileField($fieldId);; + #Create a seperate template var for each field + $var->{'profile_field_'.$fieldId.'_label' } = $fieldLabel; + $var->{'profile_field_'.$fieldId.'_value' } = $fieldValue; + $var->{'profile_field_'.$fieldId.'_raw' } = $fieldRaw; + + push(@fields, { + 'profile_field_id' => $fieldId, + 'profile_field_is_'.$fieldId => "true", + 'profile_field_label' => $fieldLabel, + 'profile_field_value' => $fieldValue, + 'profile_field_raw' => $fieldRaw + }); + } + my $categoryId = $category->getId; + my $categoryLabel = $category->getLabel; + my $shortCategoryLabel = $category->getShortLabel; + my $isActive = $categoryId eq $selected; + my $categoryIndex = $counter++; + + $var->{'profile_category_'.$categoryId."_isActive" } = $isActive; + $var->{'profile_category_'.$categoryId."_label" } = $categoryLabel; + $var->{'profile_category_'.$categoryId."_shortLabel"} = $shortCategoryLabel; + $var->{'profile_category_'.$categoryId."_fields" } = \@fields; + $var->{'profile_category_'.$categoryId."_index" } = $categoryIndex; + + push(@categories, { + 'profile_category_id' => $categoryId, + 'profile_category_isActive' => $isActive, + 'profile_category_is_'.$categoryId => "true", + 'profile_category_label' => $categoryLabel, + 'profile_category_shortLabel' => $shortCategoryLabel, + 'profile_category_index' => $categoryIndex, + 'profile_fields_loop' => \@fields, + }); + #This value will determine whether or not a valid category is active or not + $active ||= $isActive; + } + + #If not category is selected, set the first category as the active one + $categories[0]->{profile_category_isActive} = 1 unless($active); + + $var->{'profile_category_loop' } = \@categories; + $var->{'profile_user_id' } = $user->userId; + $var->{'can_edit_profile' } = $uid eq $session->user->userId; + $var->{'acceptsPrivateMessages'} = $user->acceptsPrivateMessages($session->user->userId); + $var->{'acceptsFriendsRequests'} = $user->acceptsFriendsRequests($session->user); + + $self->appendCommonVars($var); + + #Overwrite these + $var->{'user_full_name' } = $user->getWholeName; + $var->{'user_member_since' } = $user->dateCreated; + + return $self->processTemplate($var,$self->getViewTemplateId); } + 1; diff --git a/lib/WebGUI/Account/User.pm b/lib/WebGUI/Account/User.pm index ffeebc415..46f3b4d42 100644 --- a/lib/WebGUI/Account/User.pm +++ b/lib/WebGUI/Account/User.pm @@ -35,7 +35,7 @@ These subroutines are available from this package: =cut -sub editUserSettingsForm { +sub editSettingsForm { my $self = shift; my $session = $self->session; my $setting = $session->setting; @@ -61,7 +61,7 @@ sub editUserSettingsForm { =cut -sub editUserSettingsFormSave { +sub editSettingsFormSave { } #------------------------------------------------------------------- diff --git a/lib/WebGUI/Content/Account.pm b/lib/WebGUI/Content/Account.pm index c41b9e69a..619687ca7 100644 --- a/lib/WebGUI/Content/Account.pm +++ b/lib/WebGUI/Content/Account.pm @@ -58,6 +58,36 @@ These subroutines are available from this package: #------------------------------------------------------------------- +=head2 getAccountConfig ( op, configs ) + +Searches the account config array passed in and returns the hash reference which +contains the op value passed in. If no op value is found, undef is returned; + +=head3 op + +op to search for + +=head3 configs + +array ref with account config hashes + +=cut + +sub getAccountConfig { + my $class = shift; + my $session = shift; + my $module = shift; + my $configs = shift || $session->config->get("account"); + + foreach my $config (@{$configs}) { + return $config if ($config->{identifier} eq $module); + } + + return undef; +} + +#------------------------------------------------------------------- + =head2 handler ( session ) The content handler for this package. @@ -67,19 +97,25 @@ The content handler for this package. sub handler { my $session = shift; my $form = $session->form; + my $setting = $session->setting; + + my $op = $form->get("op"); + return undef unless ($op eq "account"); my $output = undef; - my $op = $session->form->get("op"); - my $configs = $session->config->get("account"); + my $module = $form->get("module") || $session->config->get("profileModuleIdentifier"); - if ($configs->{$op}) { + my $configs = $session->config->get("account"); + my $config = __PACKAGE__->getAccountConfig($session,$module,$configs); + + if (defined $config) { + #Visitor cannot do anything to the profile. return $session->privilege->insufficient if($session->user->isVisitor); - #$session->errorHandler->warn("Loading module : ".$configs->{$op}->{className}); #Create Pluggin Object #Don't eval this as pluggable will croak and we want WebGUI::URL::Content to handle the exception - my $pluggin = WebGUI::Pluggable::instanciate($configs->{$op}->{className}, "new", [ $session ] ); + my $pluggin = WebGUI::Pluggable::instanciate($config->{className}, "new", [ $session ] ); #Check to make sure pluggin is a subclass of WebGUI::Account unless($pluggin->isa('WebGUI::Account')) { @@ -91,12 +127,15 @@ sub handler { ); } + #Check to see if the user has permission to see what they are calling + return $session->privilege->insufficient unless ($pluggin->canView); + #Process the method call - my $method = $session->form->get("do") || "view"; + my $method = $form->get("do") || "view"; $method = "www_".$method; - + if($pluggin->can($method)) { - $output = eval { $pluggin->$method($session) }; + $output = $pluggin->$method; } else { WebGUI::Error::MethodNotFound->throw( @@ -108,12 +147,46 @@ sub handler { #Wrap content returned from method call into the layout my $var = {}; $var->{content} = $output; - my $layoutId = $pluggin->getLayoutTemplateId; - $output = $pluggin->processTemplate($var,$layoutId); + # Get fieldsets for avaiable account methods in the order they exist in the config file + my @pluggins = (); + foreach my $account (@{$configs}) { + #Instantiate the pluggin + #Use the currently instantiated pluggin if we are checking this pluggin + my $instance = undef; + if($account->{identifier} eq $module) { + $instance = $pluggin; + } + else { + $instance = eval { WebGUI::Pluggable::instanciate($account->{className}, "new", [ $session ] ) }; + if (my $e = WebGUI::Error->caught) { + $session->log->warn("Couldn't instantiate Account Pluggin ".$account->{className}." ... skipping"); + next; + } + elsif(!$pluggin->isa('WebGUI::Account')) { + $session->log->warn((ref $instance)." is not a subclass of WebGUI::Account ... skipping"); + next; + } + } + #Skip this module if the user can't view this + next unless ($instance->canView); + + #Push the tab variables onto the template + my %hash = %{$account}; + my $identifier = $account->{identifier}; + $hash{'is_'.$identifier} = "true"; + $hash{'url' } = $instance->getUrl("module=$identifier",1); + $hash{'isActive' } = "true" if($identifier eq $module); + WebGUI::Macro::process(\$hash{'title'}); + push(@pluggins,\%hash); + } + $var->{'account_loop'} = \@pluggins; + + my $layoutId = $pluggin->getLayoutTemplateId; + #Process the layout template + $output = $pluggin->processTemplate($var,$layoutId); #Wrap the layout in the user style - $session->http->setCacheControl("none"); - $output = $session->style->process($output,$session->setting->get("userFunctionStyleId")); + $output = $session->style->userStyle($output); } return $output; diff --git a/lib/WebGUI/Form/File.pm b/lib/WebGUI/Form/File.pm index 076c0d3d4..0c1e82542 100644 --- a/lib/WebGUI/Form/File.pm +++ b/lib/WebGUI/Form/File.pm @@ -174,6 +174,11 @@ deleting the file if it was specified. sub getValue { my $self = shift; my $value = $self->get("value"); + my $log = $self->session->log; + $log->warn("file is: ".$self->session->form->get($self->get("name")."_file")); + $log->warn("value is: ".$value); + $log->warn("action is: ".$self->session->form->param($self->privateName('action'))); + my $storage = WebGUI::Storage->get($self->session,$value); if (defined $storage) { foreach my $file (@{$storage->getFiles}) { @@ -195,6 +200,8 @@ sub getValue { } $storage->addFileFromFormPost($self->get("name")."_file",1000); my @files = @{ $storage->getFiles }; + $log->warn("storageId: ".$storage->getId); + $log->warn("number of files: ".scalar(@files)); if (scalar(@files) < 1) { $storage->delete; return undef; @@ -205,6 +212,7 @@ sub getValue { return $id; } } + $log->warn("returning: ".$value); return $value; } diff --git a/lib/WebGUI/Form/Image.pm b/lib/WebGUI/Form/Image.pm index 89d05b184..f1f923e8d 100644 --- a/lib/WebGUI/Form/Image.pm +++ b/lib/WebGUI/Form/Image.pm @@ -181,11 +181,12 @@ Displays the image using an img tag. =cut sub getValueAsHtml { - my ($self) = @_; - my $value = $self->getOriginalValue; + my ($self) = @_; + my $value = $self->getOriginalValue; return '' unless $value; my $location = WebGUI::Storage::Image->get($self->session, $value); my $file = shift @{ $location->getFiles }; + return '' unless $file; my $fileValue = sprintf qq| %s|, $location->getUrl($file), $file; return $fileValue; } diff --git a/lib/WebGUI/Group.pm b/lib/WebGUI/Group.pm index e93f2f7d1..8d65511c2 100755 --- a/lib/WebGUI/Group.pm +++ b/lib/WebGUI/Group.pm @@ -77,10 +77,11 @@ These methods are available from this class: #------------------------------------------------------------------- sub _create { - my $self = shift; - my $override = shift; + my $self = shift; + my $override = shift; + my $noAdmin = shift; $self->{_groupId} = $self->session->db->setRow("groups","groupId", $self->_defaults, $override); - $self->addGroups([3]); + $self->addGroups([3]) unless ($noAdmin); } @@ -850,7 +851,30 @@ u.expires > $time AND ( $scratchClause ) EOQ return $self->session->db->buildArrayRef($query, [ @scratchPlaceholders ]); -} +} + +#------------------------------------------------------------------- + +=head2 getUserList ( [ withoutExpired ] ) + +Returns a hash reference with key of userId and value of username for users in the group + +=head3 withoutExpired + +A boolean that if set to true will return only the groups that the user is in where +their membership hasn't expired. + +=cut + +sub getUserList { + my $self = shift; + my $withoutExpired = shift; + my $expireTime = 0; + if ($withoutExpired) { + $expireTime = $self->session->datetime->time(); + } + return $self->session->db->buildHashRef("select users.userId, users.username from users join groupings using(userId) where expireDate > ? and groupId = ? order by username asc", [$expireTime, $self->getId]); +} #------------------------------------------------------------------- @@ -1014,7 +1038,6 @@ sub isEditable { return $self->get("isEditable"); } - #------------------------------------------------------------------- =head2 lastUpdated ( ) @@ -1053,7 +1076,7 @@ sub name { #------------------------------------------------------------------- -=head2 new ( session, groupId [, overrideId ] ) +=head2 new ( session, groupId [, overrideId, noAdmin ] ) Constructor. @@ -1069,6 +1092,10 @@ The groupId of the group you're creating an object reference for. If specified a If you specified "new" for groupId, you can use this property to specify an id you wish to create, rather than having the system generate one for you. +=head3 noAdmin + +If you specified "new" for groupId, you can use this property to specify that you do not wish the admin user or group to be added to the group + =cut sub new { @@ -1078,13 +1105,14 @@ sub new { $self->{_session} = shift; $self->{_groupId} = shift; my $override = shift; + my $noAdmin = shift; my $cached = $self->{_session}->stow->get("groupObj"); return $cached->{$self->{_groupId}} if ($cached->{$self->{_groupId}}); bless $self, $class; if ($self->{_groupId} eq "new") { - $self->_create($override); + $self->_create($override,$noAdmin); } elsif ($self->{_groupId} eq "") { $self->{_group} = $self->_defaults(); diff --git a/lib/WebGUI/Inbox.pm b/lib/WebGUI/Inbox.pm index 852534dc1..a15f92a13 100644 --- a/lib/WebGUI/Inbox.pm +++ b/lib/WebGUI/Inbox.pm @@ -82,6 +82,39 @@ sub addPrivateMessage { #------------------------------------------------------------------- +=head2 canRead ( messageId [, user] ) + +Returns whether or not a user can view the message passed in. + +=head3 message + +A WebGUI::Inbox::Message object + +=head3 user + +WebGUI::User object to test against. Defaults to the current user. + +=cut + +sub canRead { + my $self = shift; + my $message = shift; + my $user = shift || $self->session->user; + + unless (ref $message eq "WebGUI::Inbox::Message") { + $self->session->log->warn("Message passed in was either empty or not a valid WebGUI::Inbox::Message. Got: ".(ref $message)); + return 0 + } + + my $userId = $message->get("userId"); + my $groupId = $message->get("groupId"); + + return ($user->userId eq $userId || (defined $groupId && $user->isInGroup($groupId))); + +} + +#------------------------------------------------------------------- + =head2 DESTROY ( ) Deconstructor. @@ -95,7 +128,7 @@ sub DESTROY { #------------------------------------------------------------------- -=head2 getMessage ( messageId ) +=head2 getMessage ( messageId [, userId] ) Returns a WebGUI::Inbox::Message object. @@ -103,17 +136,91 @@ Returns a WebGUI::Inbox::Message object. The id of the message to retrieve. +=head3 userId + +The id of the user to retrieve the message for. Defaults to the current user. + =cut sub getMessage { - my $self = shift; - return WebGUI::Inbox::Message->new($self->session, shift); -} + my $self = shift; + my $messageId = shift; + my $userId = shift; + return WebGUI::Inbox::Message->new($self->session, $messageId, $userId); +} #------------------------------------------------------------------- -=head2 getMessagesForUser ( user [ , limit ] ) +=head2 getNextMessage ( message [, userId] ) + +Returns the next message for the user + +=head3 message + +The message to find the next message for + +=head3 user + +The WebGUI::User object of the user to retrieve the message for. Defaults to the current user. + +=cut + +sub getNextMessage { + my $self = shift; + my $session = $self->session; + my $message = shift; + my $user = shift || $session->user; + + my $sql = $self->getMessageSql($user,{ + whereClause => "ibox.dateStamp < ".$message->get("dateStamp"), + sortBy => "ibox.dateStamp", + sortDir => "desc", + limit => 1 + }); + + my $message = $self->session->db->quickHashRef($sql); + + return $self->getMessage($message->{messageId}); +} + +#------------------------------------------------------------------- + +=head2 getPreviousMessage ( message [, userId] ) + +Returns the previous message for the user + +=head3 message + +The message to find the previous message for + +=head3 user + +The WebGUI::User object of the user to retrieve the message for. Defaults to the current user. + +=cut + +sub getPreviousMessage { + my $self = shift; + my $session = $self->session; + my $message = shift; + my $user = shift || $session->user; + + my $sql = $self->getMessageSql($user,{ + whereClause => "ibox.dateStamp > ".$message->get("dateStamp"), + sortBy => "ibox.dateStamp", + sortDir => "asc", + limit => 1 + }); + + my $message = $self->session->db->quickHashRef($sql); + + return $self->getMessage($message->{messageId}); +} + +#------------------------------------------------------------------- + +=head2 getMessagesForUser ( user [ , limit, page, sortBy ] ) Returns an array reference containing the most recent message objects for a given user. @@ -125,6 +232,14 @@ A user object. An integer indicating the number of messages to fetch. Defaults to 50. +=head3 page + +An integer indication the page to return. Defaults to 1 + +=head3 sortby + +The column to sort by + =cut sub getMessagesForUser { @@ -134,60 +249,263 @@ sub getMessagesForUser { my $page = shift || 1; my $sortBy = shift; - my @messages = (); - my $counter = 0; + my $p = $self->getMessagesPaginator( $user , { + sortBy => $sortBy, + sortDir => "desc", + paginateAfter => $perpage, + pageNumber => $page + + }); - my ( $sql, @bindvars ); - my $start = (($page-1) * $perpage); - my $end = $start + $page * $perpage; - my $limit = "$start, $perpage"; - - ### Here we're going to get enough rows to fill our needs ($end) from each subquery, then - ### use the UNION to grab only the rows we want to display ($limit) - - # If we have a way to sort, use that - if ( grep { $_ eq $sortBy } qw( subject sentBy dateStamp ) ) { - $sql = q{ ( SELECT messageId, userId, groupId, %s FROM inbox WHERE userId = "%s" ORDER BY %s LIMIT %s ) } - . q{ UNION } - . q{ ( SELECT messageId, userId, groupId, %s FROM inbox WHERE groupId IN ( %s ) ORDER BY %s LIMIT %s ) } - . q{ ORDER BY %s LIMIT %s } - ; - @bindvars = ( - $sortBy, $user->userId, $sortBy, $end, - $sortBy, $self->session->db->quoteAndJoin( $user->getGroupIdsRecursive ), $sortBy, $end, - $sortBy, $limit - ); - } - # Otherwise put "pending" messages above "completed" messaged and sort by date descending - else { - $sql = - q{ ( SELECT messageId, status, dateStamp FROM inbox WHERE status="pending" AND groupId IN ( %s ) ORDER BY dateStamp DESC LIMIT %s ) } - . q{ UNION } - . q{ ( SELECT messageId, status, dateStamp FROM inbox WHERE status="pending" AND userId = "%s" ORDER BY dateStamp DESC LIMIT %s ) } - . q{ UNION } - . q{ ( SELECT messageId, status, dateStamp FROM inbox WHERE status="completed" AND groupId IN ( %s ) ORDER BY dateStamp DESC LIMIT %s ) } - . q{ UNION } - . q{ ( SELECT messageId, status, dateStamp FROM inbox WHERE status="completed" AND userId = "%s" ORDER BY dateStamp DESC LIMIT %s ) } - . q{ ORDER BY status="pending" DESC, dateStamp DESC LIMIT %s } - ; - - @bindvars = ( - ( $self->session->db->quoteAndJoin( $user->getGroupIdsRecursive ), $end, - $user->userId, $end, - ) x 2, - $limit, - ); - } - - my $rs = $self->session->db->read( sprintf $sql, @bindvars ); - while ( my ( $messageId ) = $rs->array ) { - push @messages, $self->getMessage( $messageId ); - } - $rs->finish; - - return \@messages; + return $self->getMessagesOnPage($p); } +#------------------------------------------------------------------- + +=head2 getMessagesOnPage ( paginator ) + +Returns an array ref of WebGUI::Inbox::Message objects created from the current +page of data. + +=head3 paginator + +The id of the message to retrieve. + +=cut + +sub getMessagesOnPage { + my $self = shift; + my $p = shift; + my @messages = (); + + unless (defined $p and ref $p eq "WebGUI::Paginator") { + $self->session->log->warn("Paginator was not defined"); + return []; + } + + foreach my $row (@{$p->getPageData}) { + push @messages, $self->getMessage( $row->{messageId} ); + } + + return \@messages; +} + + + +#------------------------------------------------------------------- + +=head2 getMessagesPaginator ( user [, properties ] ) + +Returns an reference to a WebGUI::Paginator object filled with all the messages in a user's inbox + +=head3 user + +A user object. + +=head3 properties + +Properties which can be set to determine how many rows are returned, etc + +=head4 sortBy + +Column to sort the inbox by. Valid values are subject, sentBy, and dateStamp. Defaults to +dateStamp if value is invalid. Defaults to status="pending" DESC, dateStamp DESC if value not set. + +=head4 sortDir + +Direction to sort the results by. Defaults to desc. This only works if a sortBy value is set. + +=head4 baseUrl + +The URL of the current page including attributes. The page number will be appended to this in all links generated by the paginator. +Defaults to $session->url->pge + +=head4 paginateAfter + +The number of rows to display per page. If left blank it defaults to 25. + +=head4 formVar + +Specify the form variable the paginator should use in its links. Defaults to "pn". + +=head pageNumber + +By default the page number will be determined by looking at $self->session->form->process("pn"). If that is empty the page number will be defaulted to "1". If you'd like to override the page number specify it here. + +=cut + +sub getMessagesPaginator { + my $self = shift; + my $session = $self->session; + my $user = shift || $session->user; + my $properties = shift; + + my $userId = $user->userId; + my $sortBy = $properties->{sortBy}; + my $sortDir = $properties->{sortDir} || "desc"; + my $baseUrl = $properties->{baseUrl} || $session->url->page; + my $paginateAfter = $properties->{paginateAfter}; + my $formVar = $properties->{formVar}; + my $pageNumber = $properties->{pageNumber}; + + #Make sure a valid sortBy is passed in + if($sortBy && !WebGUI::Utility::isIn($sortBy,qw( subject sentBy dateStamp status ))) { + $sortBy = q{dateStamp} + } + #Sort by fullname if user wants to sort by who sent the message + if ($sortBy eq "sentBy") { + $sortBy = q{fullName}; + } + elsif ($sortBy eq "status") { + $sortBy = q{messageStatus}; + } + elsif($sortBy) { + $sortBy = qq{ibox.$sortBy}; + } + else { + $sortBy = q{messageStatus='pending' DESC, dateStamp DESC}; + $sortDir = q{}; + } + + my $sql = $self->getMessageSql($user, { + user => $user, + sortBy => $sortBy, + sortDir => $sortDir + }); + + #$session->log->warn($sql); + + my $p = WebGUI::Paginator->new( + $session, + $baseUrl, + $paginateAfter, + $formVar, + $pageNumber + ); + + $p->setDataByQuery($sql,undef,undef); + + return $p; +} + +#------------------------------------------------------------------- + +=head2 getMessageSql ( user, properties ) + +Returns the SQL used to return the messages in a user's inbox. + +=head3 user + +WebGUI::User object of user to get messages for. Defaults to current user. + +=head3 properties + +Hash reference of properties + +=head4 sortBy + +Column to sort by. Valid columns are: + + ibox.messageId, + ibox.subject, + ibox.sentBy, + ibox.dateStamp, + ibox.status, + messageStatus, + fullName + +=head4 sortDir + +Direction to sort by + +=head4 whereClause + +A where clause to use + +=head4 limit + +Column + +=cut + +sub getMessageSql { + my $self = shift; + my $session = $self->session; + my $user = shift || $session->user; + my $props = shift || {}; + + my $userId = $user->userId; + my $sortBy = $props->{sortBy}; + my $sortDir = $props->{sortDir}; + my $whereClause = $props->{whereClause}; + my $limit = $props->{limit}; + + if($sortBy) { + $sortBy = qq{ORDER BY $sortBy $sortDir}; + } + + if($whereClause) { + $whereClause = qq{WHERE $whereClause}; + } + + if($limit) { + $limit = qq{LIMIT $limit}; + } + + my $messageLimit = 20_000; + my $limitHalf = $messageLimit / 2; + my $limitQuarter = $messageLimit / 4; + my $userGroups = $session->db->quoteAndJoin( $user->getGroupIdsRecursive ); + + # for performance purposes don't use datasets larger than 20000 no matter how man messages are in the inbox + my $sql = qq{ + SELECT + ibox.messageId, ibox.subject, ibox.sentBy, ibox.dateStamp, + (IF(ibox.status = 'completed' or ibox.status = 'pending',ibox.status,IF(inbox_messageState.repliedTo,'replied',IF(inbox_messageState.isRead,'read','unread')))) as messageStatus, + (IF(userProfileData.firstName != '' and userProfileData.firstName is not null and userProfileData.lastName !='' and userProfileData.lastName is not null, concat(userProfileData.firstName,' ',userProfileData.lastName),users.username)) as fullName + FROM ( + ( SELECT messageId, subject, sentBy, dateStamp, status FROM inbox WHERE userId = '$userId' order by dateStamp desc limit $limitHalf) + UNION + ( SELECT messageId, subject, sentBy, dateStamp, status FROM inbox WHERE groupId IN ( $userGroups ) order by dateStamp desc limit $limitHalf ) + ) AS ibox + JOIN inbox_messageState on inbox_messageState.messageId=ibox.messageId and inbox_messageState.userId='$userId' and inbox_messageState.deleted=0 + LEFT JOIN users on users.userId=ibox.sentBy + LEFT JOIN userProfileData on userProfileData.userId=ibox.sentBy + $whereClause + $sortBy + $limit + }; + + #$session->log->warn($sql); + + return $sql; +} + + +#------------------------------------------------------------------- + +=head2 getUnreadMessageCount ( [userId] ) + +Returns the number of unread messages for the user passed in + +=head3 userId + +user to get unread message count for. Defaults to current user. + +=cut + +sub getUnreadMessageCount { + my $self = shift; + my $session = $self->session; + my $userId = shift || $session->user->userId; + + return $session->db->quickScalar( + qq{select count(*) from inbox_messageState where userId=? and deleted=0 and isRead=0 }, + [$userId] + ); +} + + #------------------------------------------------------------------- diff --git a/lib/WebGUI/Inbox/Message.pm b/lib/WebGUI/Inbox/Message.pm index 8b0438744..37af5703c 100644 --- a/lib/WebGUI/Inbox/Message.pm +++ b/lib/WebGUI/Inbox/Message.pm @@ -97,15 +97,43 @@ sub create { $self->{_properties}{subject} = $properties->{subject} || WebGUI::International->new($session)->get(523); $self->{_properties}{message} = $properties->{message}; $self->{_properties}{dateStamp} = time(); - $self->{_properties}{userId} = $properties->{userId}; + $self->{_properties}{userId} = $properties->{userId} || $session->user->userId; $self->{_properties}{groupId} = $properties->{groupId}; $self->{_properties}{sentBy} = $properties->{sentBy} || 3; - if ($self->{_properties}{status} eq "completed") { + + my $status = $self->{_properties}{status}; + + if ($status eq "completed") { $self->{_properties}{completedBy} = $session->user->userId; $self->{_properties}{completedOn} = time(); } + elsif($status ne "pending") { + $self->{_properties}{status} = "active"; + } + $self->{_messageId} = $self->{_properties}{messageId} = $session->db->setRow("inbox","messageId",$self->{_properties}); - + $self->{_userId } = $self->{_properties}{userId}; + $self->{_inbox } = $self->{_properties}; + + #Add the message state row for individual user passed in + if($self->{_properties}{userId}) { + $session->db->write( + q{ REPLACE INTO inbox_messageState (messageId,userId) VALUES (?,?) }, + [$self->{_messageId},$self->{_properties}{userId}] + ); + } + #Add the message state row for every user in the group + if($self->{_properties}{groupId}) { + my $g = WebGUI::Group->new($session,$self->{_properties}{groupId}); + my $users = $g->getAllUsers; + foreach my $userId (@{$users}) { + $session->db->write( + q{ REPLACE INTO inbox_messageState (messageId,userId) VALUES (?,?) }, + [$self->{_messageId},$userId] + ); + } + } + my $subject = (defined $properties->{emailSubject}) ? $properties->{emailSubject} : $self->{_properties}{subject}; my $mail = WebGUI::Mail::Send->create($session, { toUser=>$self->{_properties}{userId}, @@ -137,16 +165,34 @@ sub create { #------------------------------------------------------------------- -=head2 delete ( ) +=head2 delete ( userId ) -Deletes this message from the inbox. +Deletes this message from the inbox for the user passed in + +=head3 userId + +User to delete message for. If no user is passed in, the current user will be used. =cut sub delete { - my $self = shift; - my $sth = $self->session->db->prepare("delete from inbox where messageId=?"); - $sth->execute([$self->getId]); + my $self = shift; + my $session = $self->session; + my $db = $session->db; + my $messageId = $self->getId; + my $userId = shift || $self->{_userId}; + + $self->setDeleted($userId); + + my $isActive = $db->quickScalar( + q{ select count(*) from inbox_messageState where messageId=? and deleted=0 }, + [$messageId] + ); + #Delete the message from the database if everyone who was sent the message has deleted it + unless ($isActive) { + $db->write("delete from inbox where messageId=?",[$messageId]); + $db->write("delete from inbox_messageState where messageId=?",[$messageId]); + } } #------------------------------------------------------------------- @@ -158,8 +204,8 @@ Deconstructor. =cut sub DESTROY { - my $self = shift; - undef $self; + my $self = shift; + undef $self; } #------------------------------------------------------------------- @@ -189,6 +235,17 @@ An epoch date representing when the action associated with this message was comp sub get { my $self = shift; my $name = shift; + + if($name eq "status") { + my $status = $self->{_properties}{status}; + if($status eq "active") { + return "read" if($self->{_properties}{isRead}); + return "replied" if($self->{_properties}{repliedTo}); + return "unread"; + } + return $status; + } + return $self->{_properties}{$name}; } @@ -206,6 +263,48 @@ sub getId { return $self->{_messageId}; } + +#------------------------------------------------------------------- + +=head2 getStatus ( [ userId ] ) + +Gets the current status of the message for the user passed in + +=head3 userId + +The id of the user to get the status of the message for. Defaults to the current user. + +=cut + +sub getStatus { + my $self = shift; + my $userId = shift || $self->{_userId}; + + my $status = $self->{_properties}{status}; + my $statusCodes = $self->statusCodes; + + if($status eq "active") { + return $statusCodes->{"replied"} if($self->{_properties}{repliedTo}); + return $statusCodes->{"read" } if($self->{_properties}{isRead}); + return $statusCodes->{"unread" }; + } + + return $statusCodes->{$self->get("status")}; +} + +#------------------------------------------------------------------- + +=head2 isRead ( ) + +Returns whether or not the message has been read. + +=cut + +sub isRead { + my $self = shift; + return $self->{_properties}{isRead}; +} + #------------------------------------------------------------------- =head2 new ( session, messageId ) @@ -224,10 +323,31 @@ The unique id of a message. =cut sub new { - my $class = shift; - my $session = shift; + my $class = shift; + my $session = shift; my $messageId = shift; - bless {_properties=>$session->db->getRow("inbox","messageId",$messageId), _session=>$session, _messageId=>$messageId}, $class; + my $userId = shift || $session->user->userId; + + #Don't bother going on if a messageId wasn't passed in + return undef unless $messageId; + + my $inbox = $session->db->getRow("inbox","messageId",$messageId); + my $statusValues = $session->db->quickHashRef( + q{ select isRead, repliedTo, deleted from inbox_messageState where messageId=? and userId=? }, + [$messageId,$userId] + ); + + #Don't return messages that don't exist + return undef unless (scalar(keys %{$inbox})); + + #Don't return deleted messages + return undef if($statusValues->{deleted}); + + my $self = {}; + + my %properties = (%{$inbox},%{$statusValues}); + + bless {_properties=>\%properties, _inbox=>$inbox, _session=>$session, _messageId=>$messageId, _userId=>$userId}, $class; } #------------------------------------------------------------------- @@ -261,9 +381,78 @@ sub setCompleted { $self->{_properties}{status} = "completed"; $self->{_properties}{completedBy} = $userId; $self->{_properties}{completedOn} = time(); - $self->session->db->setRow("inbox","messageId",$self->{_properties}); + $self->session->db->setRow("inbox","messageId",$self->{_inbox}); + #Completed messages should also be marked read + $self->setRead($userId); } +#------------------------------------------------------------------- + +=head2 setDeleted ( [ userId ] ) + +Marks a message deleted. + +=head4 userId + +The id of the user that deleted this message. Defaults to the current user. + +=cut + +sub setDeleted { + my $self = shift; + my $userId = shift || $self->session->user->userId; + + $self->session->db->write( + q{update inbox_messageState set deleted=1 where messageId=? and userId=?}, + [$self->getId,$userId] + ); +} + +#------------------------------------------------------------------- + +=head2 setRead ( [ userId ] ) + +Marks a message read. + +=head4 userId + +The id of the user that reads this message. Defaults to the current user. + +=cut + +sub setRead { + my $self = shift; + my $userId = shift || $self->session->user->userId; + + $self->session->db->write( + q{update inbox_messageState set isRead=1 where messageId=? and userId=?}, + [$self->getId,$userId] + ); +} + +#------------------------------------------------------------------- + +=head2 setReplied ( [ userId ] ) + +Marks a message replied. + +=head4 userId + +The id of the user that replied to this message. Defaults to the current user. + +=cut + +sub setReplied { + my $self = shift; + my $userId = shift || $self->session->user->userId; + + $self->session->db->write( + q{update inbox_messageState set repliedTo=1, isRead=1 where messageId=? and userId=?}, + [$self->getId,$userId] + ); +} + + #------------------------------------------------------------------- =head2 setStatus ( status,[ userId ] ) @@ -281,22 +470,111 @@ The id of the user that completed this task. Defaults to the current user. =cut sub setStatus { - my $self = shift; - my $status = shift; - my $userId = shift || $self->session->user->userId; + my $self = shift; + my $status = shift; + my $session = $self->session; + my $userId = shift || $session->user->userId; unless ($status) { - $self->session->errorHandler->warn("No status passed in for message. Exit without update"); + $session->log->warn("No status passed in for message. Exit without update"); return undef; } - + + unless($self->isValidStatus($status)) { + $self->session->log->warn("Invalid status $status passed in for message. Exit without update"); + return undef; + } + if($status eq "completed") { $self->setCompleted($userId); return undef; } - $self->{_properties}{status} = $status; - $self->session->db->setRow("inbox","messageId",$self->{_properties}); + elsif($status eq "read") { + $self->setRead($userId); + } + elsif($status eq "unread") { + $self->setUnread($userId); + } + elsif($status eq "replied") { + $self->setReplied($userId); + } + + $self->{_properties}{status} = ( $status ne "pending") ? "active" : "pending"; + $self->session->db->setRow("inbox","messageId",$self->{_inbox}); return undef; } +#------------------------------------------------------------------- + +=head2 setUnread ( [ userId ] ) + +Marks a message unread. + +=head4 userId + +The id of the user that reads this message. Defaults to the current user. + +=cut + +sub setUnread { + my $self = shift; + my $userId = shift || $self->session->user->userId; + + $self->session->db->write( + q{update inbox_messageState set isRead=0 where messageId=? and userId=?}, + [$self->getId,$userId] + ); +} + +#------------------------------------------------------------------- + +=head2 statusCodes ( session ) + +Returns a hash ref of valid status values. Can be called as a class or instance method + +=head4 status + +The id of the user that replied to this message. Defaults to the current user. + +=cut + +sub statusCodes { + my $self = shift; + my $session = shift; + + if(ref $self eq "WebGUI::Inbox::Message") { + $session = $self->session; + } + + my $i18n = WebGUI::International->new($session); + return { + "active" => $i18n->get("inbox message status active"), + "pending" => $i18n->get(552), + "completed" => $i18n->get(350), + "unread" => $i18n->get("private message status unread"), + "read" => $i18n->get("private message status read"), + "replied" => $i18n->get("private message status replied"), + } +} + + +#------------------------------------------------------------------- + +=head2 isValidStatus ( status ) + +Returns whether or not the status passed in is valid. Can be called as a class or instance method + +=head4 status + +The id of the user that replied to this message. Defaults to the current user. + +=cut + +sub isValidStatus { + my $self = shift; + my $status = shift; + return (exists $self->statusCodes->{$status}); +} + + 1; diff --git a/lib/WebGUI/Macro/FileUrl.pm b/lib/WebGUI/Macro/FileUrl.pm index d3db012e0..556f23b4d 100644 --- a/lib/WebGUI/Macro/FileUrl.pm +++ b/lib/WebGUI/Macro/FileUrl.pm @@ -26,7 +26,7 @@ identified by it's asset URL. #------------------------------------------------------------------- -=head2 process ( url ) +=head2 process ( url, id, isStorageId, filename ) returns the file system URL if url is the URL for an Asset in the system that has storageId and filename properties. If no Asset @@ -37,13 +37,43 @@ be returned. The URL to the Asset. +head3 id + +If id is passed in, the macro will attempt to retrive the storageId using the +Id of the Asset instead of by the url + +=head3 isStorageId + +If id is passed in and the isStorageId flag is set, the macro will forgo +the asset and simply return the url of the first file it finds + +=head3 filename + +If id is passed in and the isStorageId flag is set, you may pass in filename +to specify the name of the file you'd like returned. + =cut sub process { - my $session = shift; - my $url = shift; - my $asset = WebGUI::Asset->newByUrl($session,$url); - my $i18n = WebGUI::International->new($session, 'Macro_FileUrl'); + my $session = shift; + my $url = shift; + my $id = shift; + my $isStorageId = shift; + my $filename = shift; + my $i18n = WebGUI::International->new($session, 'Macro_FileUrl'); + + #Handle storageId case + if($isStorageId && $id) { + my $store = WebGUI::Storage->get($session,$id); + $filename = $store->getFiles->[0] unless ($filename); + return "" unless ($filename); + return $store->getUrl($filename); + } + + my $asset = ($id) + ? WebGUI::Asset->newByDynamicClass($session,$id) + : WebGUI::Asset->newByUrl($session,$url); + if (not defined $asset) { return $i18n->get('invalid url'); } diff --git a/lib/WebGUI/Operation/Inbox.pm b/lib/WebGUI/Operation/Inbox.pm index c0356f564..89bbe5a9f 100644 --- a/lib/WebGUI/Operation/Inbox.pm +++ b/lib/WebGUI/Operation/Inbox.pm @@ -37,6 +37,9 @@ Operations for viewing message logs and individual messages. appends the form variables for the private message form +DEPRECATED: Do not use this method in new code. It is here for API +compatibility only + =cut sub _appendPrivateMessageForm { @@ -55,10 +58,6 @@ sub _appendPrivateMessageForm { $vars->{ message_to_label } = $i18n->get("private message to label"); $vars->{ message_to } = $userTo->username; - $vars->{ message_to } .= WebGUI::Form::hidden($session, { - name=>"uid", - value=>$userTo->userId - }); my $subject = $form->get("subject") || ""; if($subject eq "" && defined $message) { @@ -81,14 +80,10 @@ sub _appendPrivateMessageForm { value=>$form->get("message") || "", }); - $vars->{ form_header } = WebGUI::Form::formHeader($session); - $vars->{ form_header } .= WebGUI::Form::hidden($session, { - name => "op", - value => "sendPrivateMessageSave" - }); - $vars->{ form_header } .= WebGUI::Form::hidden($session, { - name => "messageId", - value => $form->get("messageId") || "", + my $messageId = $form->get("messageId") || $message->getId; + $vars->{'form_header' } = WebGUI::Form::formHeader($session,{ + action => $session->url->page->("op=account;module=inbox;do=sendMessageSave;messageId=$messageId;userId=$userTo->userId"), + extras => q{name="messageForm"} }); $vars->{ submit_button } = WebGUI::Form::submit($session,{}); @@ -104,24 +99,29 @@ sub _appendPrivateMessageForm { returns a hashref with internationalized values for message status. +DEPRECATED: Use WebGUI::Inbox::Message->statusCodes + =cut sub _status { my $session = shift; - my $i18n = WebGUI::International->new($session); - return { - "pending" =>$i18n->get(552), - "completed" =>$i18n->get(350), - "unread" =>$i18n->get("private message status unread"), - "read" =>$i18n->get("private message status read"), - "replied" =>$i18n->get("private message status replied"), - }; + return WebGUI::Inbox::Message->statusCodes($session); + #my $i18n = WebGUI::International->new($session); + #return { + # "pending" =>$i18n->get(552), + # "completed" =>$i18n->get(350), + # "unread" =>$i18n->get("private message status unread"), + # "read" =>$i18n->get("private message status read"), + # "replied" =>$i18n->get("private message status replied"), + #}; } #------------------------------------------------------------------- =head2 www_sendPrivateMessage ( ) +DEPRECATED: Use WebGUI::Account::Inbox + Form for sending private messages =cut @@ -169,6 +169,8 @@ sub www_sendPrivateMessage { =head2 www_sendPrivateMessageSave ( ) +DEPRECATED: Use WebGUI::Account::Inbox + Post process the form, check for required fields, handle inviting users who are already members (determined by email address) and send the email. @@ -244,6 +246,8 @@ sub www_sendPrivateMessageSave { =head2 www_viewInbox ( ) +DEPRECATED: Use WebGUI::Account::Inbox + Templated display all messages for the current user. =cut @@ -335,6 +339,8 @@ sub www_viewInbox { =head2 www_deletePrivateMessage ( ) +DEPRECATED: Use WebGUI::Account::Inbox + Mark a private message in the inbox as deleted. =cut @@ -356,6 +362,8 @@ sub www_deletePrivateMessage { =head2 www_viewInboxMessage ( ) +DEPRECATED: Use WebGUI::Account::Inbox + Templated display of a single message for the user. =cut diff --git a/lib/WebGUI/Operation/Profile.pm b/lib/WebGUI/Operation/Profile.pm index bfa3b8c72..4abf01362 100644 --- a/lib/WebGUI/Operation/Profile.pm +++ b/lib/WebGUI/Operation/Profile.pm @@ -46,7 +46,7 @@ These methods are available from this package: Returns an array of hashes for required profile fields. This array is ready to be used as template variables in the WebGUI template system. -This method is deprecated, and should not be used in new code. Use +DEPRECATED - This method is deprecated, and should not be used in new code. Use the getRequiredFields method from WebGUI::ProfileField and specify the translation to template variables directly instead. @@ -80,6 +80,9 @@ duplicated in the system. Returns true of false. Will return false if the email address passed in is same as the email address of the current user. +DEPRECATED - This method is deprecated, and should not be used in new code. Use +the isDuplicate method from WebGUI::ProfileField instead + =head3 email email address to check for duplication @@ -103,6 +106,9 @@ sub isDuplicateEmail { Saves profile data to a user's profile. Does not validate any of the data. +DEPRECATED - This method is deprecated, and should not be used in new code. Use +the saveProfileFields method from WebGUI::Account::Profile instead + =head3 session WebGUI session object @@ -122,9 +128,7 @@ sub saveProfileFields { my $u = shift; my $profile = shift; - foreach my $fieldName (keys %{$profile}) { - $u->profileField($fieldName,${$profile}{$fieldName}); - } + WebGUI::Account::Profile->saveProfileFields($session,$u,$profile); } #------------------------------------------------------------------- @@ -134,6 +138,9 @@ sub saveProfileFields { Validates profile data from the session form variables. Returns processed data, warnings and errors. +DEPRECATED - This method is deprecated, and should not be used in new code. Use +the validateProfileData method from WebGUI::Account::Profile instead + There are two levels of validation: =over 4 @@ -191,6 +198,8 @@ makes a large set of template variables which are passed to a template for prese and styling. The default template is PBtmpl0000000000000051 and is not user selectable. +DEPRECATED - Use WebGUI::Account::Profile::www_edit + Calls www_editProfileSave on submission. =head3 session @@ -253,6 +262,9 @@ object. Returns the user to WebGUI::Operation::Auth::www_auth when done. + +DEPRECATED: Use WebGUI::Account::Profile::www_editSave + =head3 session A reference to the current session. @@ -281,6 +293,8 @@ Validates that the user requesting the profile data is allowed to see it. Similarly to www_editProfile, this method is templated. The default template is PBtmpl0000000000000052. The template is not user selectable. +DEPRECATED: Use WebGUI::Account::Profile::www_view + =head3 session A reference to the current session. diff --git a/lib/WebGUI/Operation/ProfileSettings.pm b/lib/WebGUI/Operation/ProfileSettings.pm index 92644dffa..8ddcbb5d9 100644 --- a/lib/WebGUI/Operation/ProfileSettings.pm +++ b/lib/WebGUI/Operation/ProfileSettings.pm @@ -169,6 +169,12 @@ sub www_editProfileCategory { -hoverHelp => $i18n->get('470 description'), -value => $data->{label}, ); + $f->text( + -name => "shortLabel", + -label => $i18n->get('category short name'), + -hoverHelp => $i18n->get('category short name description'), + -value => $data->{shortLabel}, + ); $f->yesNo( -name=>"visible", -label=>$i18n->get(473), @@ -198,10 +204,11 @@ sub www_editProfileCategorySave { my $session = shift; return $session->privilege->adminOnly() unless canView($session); my %data = ( - label=>$session->form->text("label"), - visible=>$session->form->yesNo("visible"), - editable=>$session->form->yesNo("editable"), - ); + label =>$session->form->text("label"), + shortLabel =>$session->form->text("shortLabel"), + visible =>$session->form->yesNo("visible"), + editable =>$session->form->yesNo("editable"), + ); if ($session->form->process("cid") eq "new") { my $category = WebGUI::ProfileCategory->create($session,\%data); } else { diff --git a/lib/WebGUI/Operation/Settings.pm b/lib/WebGUI/Operation/Settings.pm index c980492d7..1c4e83f00 100644 --- a/lib/WebGUI/Operation/Settings.pm +++ b/lib/WebGUI/Operation/Settings.pm @@ -632,8 +632,8 @@ sub www_editSettings { # Get fieldsets for avaiable account methods my $accountConfigs = $session->config->get("account"); - foreach my $accountKey (keys %{$accountConfigs}) { - my $account = $accountConfigs->{$accountKey}; + + foreach my $account (@{$accountConfigs}) { #Create the instance my $className = $account->{className}; @@ -645,7 +645,7 @@ sub www_editSettings { } #Get the content of the settings form from the instance - my $settingsForm = $instance->editUserSettingsForm; + my $settingsForm = $instance->editSettingsForm; #If editUserSettingsForm is empty, skip it next if $settingsForm eq ""; @@ -698,6 +698,22 @@ sub www_saveSettings { } } + # Save account pluggin settings + my $accountConfigs = $session->config->get("account"); + foreach my $account (@{$accountConfigs}) { + #Create the instance + my $className = $account->{className}; + my $instance = eval { WebGUI::Pluggable::instanciate($className,"new",[ $session ]) }; + + if ( my $e = WebGUI::Error->caught ) { + $session->log->warn("Could not instantiate account pluggin $className...skipping"); + next; + } + #Save the settings + $instance->editSettingsFormSave; + } + + ### Handle special settings # Reset login message seen numbers if ( $session->form->get( 'showMessageOnLoginReset' ) ) { diff --git a/lib/WebGUI/Paginator.pm b/lib/WebGUI/Paginator.pm index 45111c606..2cce878ee 100644 --- a/lib/WebGUI/Paginator.pm +++ b/lib/WebGUI/Paginator.pm @@ -486,6 +486,7 @@ sub getPageLinks { "pagination.url" => '', "pagination.text" => $i+1, 'pagination.range' => ($first+1) . "-" . ($last+1), + 'pagination.activePage' => "true", }; } else { push @pages, '
'.($i+1).''; diff --git a/lib/WebGUI/ProfileCategory.pm b/lib/WebGUI/ProfileCategory.pm index b0eac652c..062746f08 100644 --- a/lib/WebGUI/ProfileCategory.pm +++ b/lib/WebGUI/ProfileCategory.pm @@ -177,6 +177,20 @@ sub getLabel { return WebGUI::Operation::Shared::secureEval($self->session,$self->get("label")); } +#------------------------------------------------------------------- + +=head2 getShortLabel ( ) + +Returns the eval'd label for this category. + +=cut + +sub getShortLabel { + my $self = shift; + return WebGUI::Operation::Shared::secureEval($self->session,$self->get("shortLabel")); +} + + #------------------------------------------------------------------- =head2 hasProtected ( ) @@ -332,6 +346,10 @@ A hash reference containing the properties to be updated. A perl structure that will return a scalar. Defaults to 'Undefined'. +=head4 shortLabel + +A perl structure that will return a scalar. Defaults to 'Undefined'. + =head4 visible A boolean indicating whether the fields in this category should be visible when a user views a user's profile. @@ -353,6 +371,7 @@ sub set { $properties->{editable} = 0 unless ($properties->{editable} == 1); $properties->{protected} = 0 unless ($properties->{protected} == 1); $properties->{label} = 'Undefined' if ($properties->{label} =~ /^[\"\']*$/); + $properties->{shortLabel} = 'Undefined' if ($properties->{shortLabel} =~ /^[\"\']*$/); $properties->{profileCategoryId} = $self->getId; $self->session->db->setRow("userProfileCategory","profileCategoryId",$properties); } diff --git a/lib/WebGUI/ProfileField.pm b/lib/WebGUI/ProfileField.pm index f6eba889d..ec4a493d2 100644 --- a/lib/WebGUI/ProfileField.pm +++ b/lib/WebGUI/ProfileField.pm @@ -253,6 +253,7 @@ sub formField { $properties->{value} = WebGUI::Operation::Shared::secureEval($self->session,$properties->{dataDefault}); } } + if ($withWrapper == 1) { return WebGUI::Form::DynamicField->new($self->session,%{$properties})->toHtmlWithWrapper; } elsif ($withWrapper == 2) { @@ -265,17 +266,24 @@ sub formField { #------------------------------------------------------------------- -=head2 formProcess ( ) +=head2 formProcess ( [user] ) Returns the value retrieved from a form post. =cut sub formProcess { - my $self = shift; - my $u = shift || $self->session->user; + my $self = shift; + my $u = shift || $self->session->user; + my $userId = $u->userId; + my $properties = $self->formProperties({value => $u->profileField($self->getId)}); - my $result = $self->session->form->process($self->getId,$self->get("fieldType"),WebGUI::Operation::Shared::secureEval($self->session,$self->get("dataDefault")), $properties); + my $result = $self->session->form->process( + $self->getId, + $self->get("fieldType"), + WebGUI::Operation::Shared::secureEval($self->session,$self->get("dataDefault")), + $properties + ); if (ref $result eq "ARRAY") { my @results = @$result; for (my $count=0;$count_listFieldsWhere($session, "f.required = 1 OR f.editable = 1 OR f.showAtRegistration = 1"); + return $class->_listFieldsWhere($session, "c.editable=1 AND (f.required = 1 OR f.editable = 1 OR f.showAtRegistration = 1)"); } #------------------------------------------------------------------- @@ -448,6 +457,7 @@ sub getRegistrationFields { return $class->_listFieldsWhere($session, "f.showAtRegistration = 1"); } +#------------------------------------------------------------------- =head2 getPasswordRecoveryFields ( session ) Returns an array reference of profile field objects that are required @@ -463,6 +473,31 @@ sub getPasswordRecoveryFields { #------------------------------------------------------------------- +=head2 isDuplicate( fieldValue ) + +Checks the value of the field to see if it is duplicated in the system. Returns true of false. + +=head3 fieldValue + +value to check for duplicates against + +=cut + +sub isDuplicate { + my $self = shift; + my $session = $self->session; + + my $fieldId = $self->getId; + my $value = shift; + + my $sql = qq{select count(*) from userProfileData where $fieldId = ? and userId <> ?}; + my ($duplicate) = $session->db->quickArray($sql,[$value, $session->user->userId]); + + return ($duplicate > 0); +} + +#------------------------------------------------------------------- + =head2 isEditable ( ) Returns a boolean indicating whether this field may be editable by a user. @@ -503,6 +538,30 @@ sub isRequired { #------------------------------------------------------------------- +=head2 isValid ( [fieldValue] ) + +Validates the profile field returning true (1) if valid or false(1) if false + +=head3 fieldValue + +value to validate the field against + +=cut + +sub isValid { + my $self = shift; + my $fieldValue = shift; + + #If the field value is an array ref, set the value to the first element + if(ref $fieldValue eq "ARRAY") { + $fieldValue = $fieldValue->[0]; + } + + return !$self->isRequired || ($self->isRequired && $fieldValue ne ""); +} + +#------------------------------------------------------------------- + =head2 isViewable ( ) Returns a boolean indicating whether this field may be viewed by a user. diff --git a/lib/WebGUI/Storage.pm b/lib/WebGUI/Storage.pm index 228a0b066..0f07d3b35 100644 --- a/lib/WebGUI/Storage.pm +++ b/lib/WebGUI/Storage.pm @@ -226,10 +226,13 @@ sub addFileFromFormPost { require Apache2::Upload; my $filename; my $attachmentCount = 1; + $self->session->log->warn("trying to uplaod: ".$formVariableName); foreach my $upload ($self->session->request->upload($formVariableName)) { - $self->session->errorHandler->info("Trying to get " . $upload->filename); + $self->session->errorHandler->warn("Trying to get " . $upload->filename); return $filename if $attachmentCount > $attachmentLimit; my $tempFilename = $upload->filename(); + $self->session->log->warn("templFile is: ".$tempFilename); + next unless $tempFilename; next unless $upload->size > 0; next if ($upload->size > 1024 * $self->session->setting->get("maxAttachmentSize")); diff --git a/lib/WebGUI/User.pm b/lib/WebGUI/User.pm index b392cced4..57c63ab34 100644 --- a/lib/WebGUI/User.pm +++ b/lib/WebGUI/User.pm @@ -114,6 +114,9 @@ sub acceptsPrivateMessages { my $self = shift; my $userId = shift; + return 0 if ($self->isVisitor); #Visitor can't get private messages + return 0 if ($self->userId eq $userId); #Can't send private messages to yourself + my $pmSetting = $self->profileField('allowPrivateMessages'); return 0 if ($pmSetting eq "none"); @@ -131,6 +134,33 @@ sub acceptsPrivateMessages { #------------------------------------------------------------------- +=head2 acceptsFriendsRequests ( user ) + +Returns whether or this user will accept friends requests from the user passed in + +=head3 user + +WebGUI::User object to check to see if user will accept requests from. + +=cut + +sub acceptsFriendsRequests { + my $self = shift; + my $user = shift; + + return 0 unless ($user && ref $user eq "WebGUI::User"); #Sanity checks + return 0 if($self->isVisitor); #Visitors can't have friends + return 0 if($self->userId eq $user->userId); #Can't be your own friend (why would you want to be?) + + my $friends = WebGUI::Friends->new($self->session,$self); + return 0 if ($friends->isFriend($user->userId)); #Already a friend + return 0 if ($friends->isInvited($user->userId)); #Invitation already sent + + return $self->profileField('ableToBeFriend'); #Return profile setting +} + +#------------------------------------------------------------------- + =head2 authMethod ( [ value ] ) Returns the authentication method for this user. @@ -288,13 +318,12 @@ Returns the WebGUI::Group for this user's Friend's Group. sub friends { my $self = shift; if ($self->{_user}{"friendsGroup"} eq "") { - my $myFriends = WebGUI::Group->new($self->session, "new"); + my $myFriends = WebGUI::Group->new($self->session, "new",0,1); $myFriends->name($self->username." Friends"); $myFriends->description("Friends of user ".$self->userId); $myFriends->expireOffset(60*60*24*365*60); $myFriends->showInForms(0); $myFriends->isEditable(0); - $myFriends->deleteUsers(['3']); $self->uncache; $self->{_user}{"friendsGroup"} = $myFriends->getId; $self->{_user}{"lastUpdated"} = $self->session->datetime->time(); @@ -387,6 +416,31 @@ sub getGroupIdsRecursive { return [ keys %groupIds ]; } +#------------------------------------------------------------------- + +=head2 getProfileUrl ( [page] ) + +Returns a link to the user's profile + +=head3 page + +If page is passed in, the profile ops will be appended to the page, otherwise +the method will return the ops appended to the current page. + +=cut + +sub getProfileUrl { + my $self = shift; + my $session = $self->session; + my $page = shift || $session->url->page; + + my $identifier = $session->config->get("profileModuleIdentifier"); + + return qq{$page?op=account;module=$identifier;do=view;uid=}.$self->userId; + +} + + #------------------------------------------------------------------- =head2 getWholeName ( ) @@ -404,6 +458,21 @@ sub getWholeName { return $self->profileField("alias") || $self->username; } + +#------------------------------------------------------------------- + +=head2 hasFriends ( ) + +Returns whether or not the user has any friends on the site. + +=cut + +sub hasFriends { + my $self = shift; + my $users = $self->friends->getUsers(1); + return scalar(@{$users}) > 0; +} + #------------------------------------------------------------------- # This method is depricated and is provided only for reverse compatibility. See WebGUI::Auth instead. sub identifier { diff --git a/lib/WebGUI/i18n/English/Account_Inbox.pm b/lib/WebGUI/i18n/English/Account_Inbox.pm index ad27f61e0..39d2732c4 100644 --- a/lib/WebGUI/i18n/English/Account_Inbox.pm +++ b/lib/WebGUI/i18n/English/Account_Inbox.pm @@ -9,7 +9,276 @@ our $I18N = { context => q{Tab label for Inbox Account pluggin}, }, + 'inbox style template label' => { + message => q|Style Template|, + lastUpdated => 1119068809 + }, + + 'inbox style template hoverHelp' => { + message => q|Select a style template from the list to enclose the inbox in.|, + lastUpdated => 1119068809 + }, + + 'inbox layout template label' => { + message => q|Edit Layout Template|, + lastUpdated => 1119068809 + }, + 'inbox layout template hoverHelp' => { + message => q{Choose a layout from the list to display the various account pluggins that are editable by the current user as well as the contents of the one currently chosen}, + lastUpdated => 1119068809 + }, + + 'inbox view template label' => { + message => q|View Template|, + lastUpdated => 1119068809 + }, + + 'inbox view template hoverHelp' => { + message => q|Choose the main template for viewing the inbox|, + lastUpdated => 1119068809 + }, + + 'inbox view message template label' => { + message => q|View Message Template|, + lastUpdated => 1119068809 + }, + + 'inbox view message template hoverHelp' => { + message => q|Choose the template for viewing a message in the inbox|, + lastUpdated => 1119068809 + }, + + 'inbox message confirm template label' => { + message => q|Inbox Message Confirm Template|, + lastUpdated => 1119068809 + }, + + 'inbox message confirm template hoverHelp' => { + message => q|Choose the template for displaying confirmation that a message has been sent|, + lastUpdated => 1119068809 + }, + + 'inbox error message template label' => { + message => q|Inbox Error Message Template|, + lastUpdated => 1119068809 + }, + + 'inbox error message template hoverHelp' => { + message => q|Choose the template for viewing inbox errors|, + lastUpdated => 1119068809 + }, + + 'inbox manage invitations template label' => { + message => q|Manage Invitations Template|, + lastUpdated => 1119068809 + }, + + 'inbox manage invitations template hoverHelp' => { + message => q|Choose the template to user for managing invitations|, + lastUpdated => 1119068809 + }, + + 'invitation error message template label' => { + message => q|Inbox Error Message Template|, + lastUpdated => 1119068809 + }, + + 'invitation error message template hoverHelp' => { + message => q|Choose the template for viewing inbox errors|, + lastUpdated => 1119068809 + }, + + 'subject label' => { + message => q|Subject|, + lastUpdated => 1119068809 + }, + + 'status label' => { + message => q{Status}, + lastUpdated => 1119068809 + }, + + 'date label' => { + message => q{Date}, + lastUpdated => 1119068809 + }, + + 'received label' => { + message => q{Received}, + lastUpdated => 1119068809 + }, + + 'recipients label' => { + message => q{Add Recipients}, + lastUpdated => 1119068809 + }, + + 'from label' => { + message => q{From}, + lastUpdated => 1119068809 + }, + + 'to label' => { + message => q{To}, + lastUpdated => 1119068809 + }, + + 'member since' => { + message => q{Member Since }, + lastUpdated => 1119068809 + }, + + 'delete label' => { + message => q{Delete}, + lastUpdated => 1119068809 + }, + + 'view my profile' => { + message => q{view my profile as others see it}, + lastUpdated => 1119068809 + }, + + 'messages label' => { + message => q{Messages}, + lastUpdated => 1119068809 + }, + + 'invitations label' => { + message => q{Invitations}, + lastUpdated => 1119068809 + }, + + 'previous label' => { + message => q{Previous}, + lastUpdated => 1119068809 + }, + + 'next label' => { + message => q{Next}, + lastUpdated => 1119068809 + }, + + 'reply label' => { + message => q{Reply}, + lastUpdated => 1119068809 + }, + + 'delete label' => { + message => q{Delete}, + lastUpdated => 1119068809 + }, + + 'cancel label' => { + message => q{Cancel}, + lastUpdated => 1119068809 + }, + + 'back label' => { + message => q{Back to Inbox}, + lastUpdated => 1119068809 + }, + + 'new message label' => { + message => q{New Message}, + lastUpdated => 1119068809 + }, + + 'send label' => { + message => q{Send}, + lastUpdated => 1181019679, + }, + + 'no access' => { + message => q{You do not have permission to view this message.}, + lastUpdated => 1119068809 + }, + + 'no reply error' => { + message => q{You do not have permission to reply to this message.}, + lastUpdated => 1119068809 + }, + + 'system message error' => { + message => q{This message was sent by the system and cannot be replied to}, + lastUpdated => 1119068809 + }, + + 'message does not exist' => { + message => q{The message you are trying to view has been deleted.}, + lastUpdated => 1119068809 + }, + + 'message count' => { + message => q{messages}, + lastUpdated => 1119068809 + }, + + 'compose message label' => { + message => q{Compose new message}, + lastUpdated => 1119068809 + }, + + 'reply message label' => { + message => q{Reply to message}, + lastUpdated => 1119068809 + }, + + 'no self error' => { + message => q|You may not send messages to yourself.|, + lastUpdated => 1181019679, + }, + + 'no friends error' => { + message => q{You do not have any active friends in the system. If you wish to send a new private message to a user without having to locate their profile, you must first add them as a friend.}, + lastUpdated => 1181019679, + }, + + 'no friends hover' => { + message => q{You must have active friends in the system if you wish to send new private messages without having to first locate their profile}, + lastUpdated => 1181019679, + }, + + 'no subject error' => { + message => q{You have not entered a subject for this message}, + lastUpdated => 1181019679, + }, + + 'no message error' => { + message => q{You have not entered a message}, + lastUpdated => 1181019679, + }, + + 'no user error' => { + message => q{You have not selected anyone to send this message to}, + lastUpdated => 1181019679, + }, + + 'blocked error' => { + message => q|This user does not wish to receive private messages.|, + lastUpdated => 1181019679, + }, + + 'remove text' => { + message => q{remove}, + lastUpdated => 1181019679, + }, + + 'update label' => { + message => q{Update}, + lastUpdated => 1181019679, + }, + + 'message sent label' => { + message => q{Message Sent}, + lastUpdated => 1181019679, + }, + + 'message sent text' => { + message => q{Your message has been sent successfully}, + lastUpdated => 1181019679, + }, + }; 1; diff --git a/lib/WebGUI/i18n/English/Account_Profile.pm b/lib/WebGUI/i18n/English/Account_Profile.pm index 621e24fde..27153da32 100644 --- a/lib/WebGUI/i18n/English/Account_Profile.pm +++ b/lib/WebGUI/i18n/English/Account_Profile.pm @@ -15,17 +15,17 @@ our $I18N = { }, 'profile style template hoverHelp' => { - message => q|Select a style template from the list to enclose your Wobject if it is viewed directly. If the Wobject is displayed as part of a Layout Asset, the Layout Asset's Style Template is used instead.|, + message => q|Select a style template from the list to enclose the inbox in.|, lastUpdated => 1119068809 }, 'profile layout template label' => { - message => q|Layout Template|, + message => q|Edit Layout Template|, lastUpdated => 1119068809 }, 'profile layout template hoverHelp' => { - message => q|Choose a layout from the list to display the various account pluggins and the contents of the one currently chosen|, + message => q{Choose a layout from the list to display the various account pluggins that are editable by the current user as well as the contents of the one currently chosen}, lastUpdated => 1119068809 }, @@ -48,6 +48,71 @@ our $I18N = { message => q|Choose the main template for editing a profile|, lastUpdated => 1119068809 }, + + 'profile edit layout template label' => { + message => q{Display Layout Template}, + lastUpdated => 1119068809 + }, + + 'profile edit layout template hoverHelp' => { + message => q{Choose a layout from the list to display the various account pluggins that are viewable by others as well as the contents of the one currently chosen}, + lastUpdated => 1119068809 + }, + + 'required error' => { + message => q|%s is required.|, + lastUpdated => 1031514049 + }, + + 'language not installed error' => { + message => q|%s is not installed. Please select another language|, + lastUpdated => 1031514049 + }, + + 'email already in use error' => { + message => q|The email address is already in use. Please use a different email address.|, + lastUpdated => 1068703399 + }, + + 'visitor profile restricted' => { + message => q|The visitor profile is restricted|, + lastUpdated => 1068703399 + }, + + 'edit my profile' => { + message => q|edit my profile|, + lastUpdated => 1068703399 + }, + + 'view my profile' => { + message => q|view my profile|, + lastUpdated => 1068703399 + }, + + 'profile as others label' => { + message => q{view my profile as others see it}, + lastUpdated => 1119068809 + }, + + 'member since' => { + message => q{Member Since }, + lastUpdated => 1119068809 + }, + + 'send private message label' => { + message => q{Send Private Message}, + lastUpdated => 1119068809 + }, + + 'send friend request label' => { + message => q{Send Friend Request}, + lastUpdated => 1119068809 + }, + + 'back label' => { + message => q{go back}, + lastUpdated => 1119068809 + } }; 1; diff --git a/lib/WebGUI/i18n/English/WebGUI.pm b/lib/WebGUI/i18n/English/WebGUI.pm index f58144ee1..68abf64aa 100644 --- a/lib/WebGUI/i18n/English/WebGUI.pm +++ b/lib/WebGUI/i18n/English/WebGUI.pm @@ -188,6 +188,11 @@ our $I18N = { lastUpdated => 1031514049 }, + 'home info short' => { + message => q|Home|, + lastUpdated => 1031514049 + }, + '118' => { message => q|Anonymous Registration|, lastUpdated => 1031514049 @@ -617,6 +622,11 @@ our $I18N = { lastUpdated => 1031514049 }, + 'demographic info short' => { + message => q|Demographic|, + lastUpdated => 1031514049 + }, + '39' => { message => q|You do not have sufficient privileges to access this page.|, lastUpdated => 1031514049 @@ -835,6 +845,11 @@ to add or remove users from their groups. lastUpdated => 1031514049 }, + 'preferences short' => { + message => q|Preferences|, + lastUpdated => 1031514049 + }, + '1026' => { message => q|Allow rich edit?|, lastUpdated => 1065966219 @@ -1247,6 +1262,11 @@ You must be using mod_perl and configure PerlSetEnv SYBASE /opt/sybase/11.0.2 message => q|Miscellaneous Information|, lastUpdated => 1031514049 }, + + 'misc info short' => { + message => q|Miscellaneous|, + lastUpdated => 1031514049 + }, '967' => { message => q|Empty everyone's trash.|, @@ -1516,6 +1536,11 @@ sent in HTML format. No attachments can be included.|, lastUpdated => 1031514049 }, + 'work info short' => { + message => q|Work|, + lastUpdated => 1031514049 + }, + '429' => { message => q|Login Time|, lastUpdated => 1031514049 @@ -1906,6 +1931,11 @@ This group could then be named "Employees in HMO 1", and would allow you to rest lastUpdated => 1031514049 }, + 'contact info short' => { + message => q|Contact Info|, + lastUpdated => 1031514049 + }, + '230' => { message => q|Message|, lastUpdated => 1031514049 @@ -2247,6 +2277,11 @@ This group could then be named "Employees in HMO 1", and would allow you to rest lastUpdated => 1031514049 }, + 'personal info short' => { + message => q|Personal|, + lastUpdated => 1031514049 + }, + '317' => { message => q|ICQ UIN|, lastUpdated => 1031514049 @@ -3539,6 +3574,11 @@ LongTruncOk=1

message => q|Read|, lastUpdated => 1181019679, }, + + 'inbox message status active' => { + message => q|Active|, + lastUpdated => 1181019679, + }, 'private message prev label' => { message => q|Previous|, diff --git a/lib/WebGUI/i18n/English/WebGUIProfile.pm b/lib/WebGUI/i18n/English/WebGUIProfile.pm index 5d4e671d6..09387ffa1 100644 --- a/lib/WebGUI/i18n/English/WebGUIProfile.pm +++ b/lib/WebGUI/i18n/English/WebGUIProfile.pm @@ -17,6 +17,16 @@ our $I18N = { lastUpdated => 1031514049 }, + 'category short name' => { + message => q|Category Short Name|, + lastUpdated => 1031514049 + }, + + 'category short name description' => { + message => q|The short name of the this category.|, + lastUpdated => 1122315199, + }, + '475' => { message => q|Field Name|, lastUpdated => 1031514049 diff --git a/www/extras/FileUploadControl.js b/www/extras/FileUploadControl.js index 53e6ece14..687254f73 100755 --- a/www/extras/FileUploadControl.js +++ b/www/extras/FileUploadControl.js @@ -85,7 +85,7 @@ function FileUploadControl_swapImage(firedobj) { var img = row.childNodes[0].childNodes[0]; img.src = imgPath; img.style.visibility="visible"; - img.alt = alternate; + img.alt = alternative; } //removes a row from the control