diff --git a/docs/changelog/7.x.x.txt b/docs/changelog/7.x.x.txt index ddf3c9a94..8bbc52dc6 100644 --- a/docs/changelog/7.x.x.txt +++ b/docs/changelog/7.x.x.txt @@ -1,5 +1,10 @@ 7.6.4 - Brand new Survey system. Make sure to export your old results as they will + - New pluggable framework added for cutsomizing WebGUI's Account system + - New Profile Account module added providing a better interface for users to view and update their profile + - New Inbox Account module added providing a better interface into WebGUI's various messaging systems + - New Friends Account module added providing a better interface into WebGUI's friends system + - The Display Account and My Purchases interfaces have been added to the new Account system not be imported, only the surveys themselves. - Made syndicated content asset use cache. - Added Cashier/Point of Sale mode for the Shop. diff --git a/docs/gotcha.txt b/docs/gotcha.txt index 940b99a09..f5c59fa28 100644 --- a/docs/gotcha.txt +++ b/docs/gotcha.txt @@ -9,6 +9,12 @@ save you many hours of grief. 7.6.4 -------------------------------------------------------------------- + * The user facing portions of WebGUI's profile, inbox, and friends systems + have been completely updated. No data will be lost but all templates + including custom templates that are related to these systems will be deleted + on upgrade. Please make sure you export your custom templates prior to + upgrading as you will need to modify them for the new system. + * The Survey system has been completely updated. Please make sure you create full backups of your survey results and export them as needed. Results will not be imported into the new Survey system. Your old surveys diff --git a/docs/upgrades/packages-7.6.4/root_import_account.wgpkg b/docs/upgrades/packages-7.6.4/root_import_account.wgpkg new file mode 100644 index 000000000..c97df1193 Binary files /dev/null and b/docs/upgrades/packages-7.6.4/root_import_account.wgpkg differ diff --git a/docs/upgrades/upgrade_7.6.3-7.6.4.pl b/docs/upgrades/upgrade_7.6.3-7.6.4.pl index 7e4d6302d..151182bc3 100644 --- a/docs/upgrades/upgrade_7.6.3-7.6.4.pl +++ b/docs/upgrades/upgrade_7.6.3-7.6.4.pl @@ -34,7 +34,8 @@ my $session = start(); # this line required migrateSurvey($session); addVersionTagMode($session); addPosMode($session); - +fixFriendsGroups( $session ); +upgradeAccount( $session ); finish($session); # this line required @@ -305,6 +306,195 @@ CREATE TABLE `Survey_tempReport` ( "); } +#---------------------------------------------------------------------------- +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; + my $config = $session->config; + my $setting = $session->setting; + + 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",[ + { + identifier => "profile", + title => "^International(title,Account_Profile);", + className => "WebGUI::Account::Profile" + }, + { + identifier => "inbox", + title => "^International(title,Account_Inbox);", + className => "WebGUI::Account::Inbox" + }, + { + identifier => "friends", + title => "^International(title,Account_Friends);", + className => "WebGUI::Account::Friends" + }, + { + identifier => "shop", + title => "^International(title,Account_Shop);", + className => "WebGUI::Account::Shop" + }, + { + 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})) { + my @newHandlers; + for my $handler ( @{ $oldHandlers } ) { + if ( $handler eq "WebGUI::Content::Operation" ) { + push @newHandlers, "WebGUI::Content::Account"; + } + push @newHandlers, $handler; + } + $session->config->set( "contentHandlers", \@newHandlers ); + } + + #Add the settings for the profile module + $setting->add("profileStyleTemplateId",""); #Use the userStyle by default + $setting->add("profileLayoutTemplateId","N716tpSna0iIQTKxS4gTWA"); + $setting->add("profileEditLayoutTemplateId","FJbUTvZ2nUTn65LpW6gjsA"); + $setting->add("profileEditTemplateId","75CmQgpcCSkdsL-oawdn3Q"); + $setting->add("profileViewTempalteId","2CS-BErrjMmESOtGT90qOg"); + $setting->add("profileErrorTempalteId","MBmWlA_YEA2I6D29OMGtRg"); + + #Add the settings for the inbox module + $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("inboxMessageConfirmationTemplateId","DUoxlTBXhVS-Zl3CFDpt9g"); + #Invitations + $setting->add("inboxManageInvitationsTemplateId","1Q4Je3hKCJzeo0ZBB5YB8g"); + $setting->add("inboxViewInvitationTemplateId","VBkY05f-E3WJS50WpdKd1Q"); + $setting->add("inboxInvitationConfirmTemplateId","5A8Hd9zXvByTDy4x-H28qw"); + + #Add the settings for the friends module + $setting->add("friendsStyleTemplateId",""); #Use the userStyle by default + $setting->add("friendsLayoutTempalteId","N716tpSna0iIQTKxS4gTWA"); + $setting->add("friendsViewTemplateId","1Yn_zE_dSiNuaBGNLPbxtw"); + $setting->add("friendsEditTemplateId","AZFU33p0jpPJ-E6qLSWZng"); + $setting->add("friendsSendRequestTemplateId","AGJBGviWGAwjnwziiPjvDg"); + $setting->add("friendsErrorTemplateId","7Ijdd8SW32lVgg2H8R-Aqw"); + $setting->add("friendsConfirmTemplateId","K8F0j_cq_jgo8dvWY_26Ag"); + $setting->add("friendsRemoveConfirmTemplateId","G5V6neXIDiFXN05oL-U3AQ"); + + #Add the settings for the user module + $setting->add("userAccountStyleTemplateId",""); #Use the userStyle by default + $setting->add("userAccountLayoutTemplateId","9ThW278DWLV0-Svf68ljFQ"); + + #Add the settings for the shop module + $setting->add("shopStyleTemplateId",""); #Use the userStyle by default + $setting->add("shopLayoutTemplateId","aUDsJ-vB9RgP-AYvPOy8FQ"); + + #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'}); + + $session->db->write(q{alter table userProfileData modify publicProfile char(10) default 'none'}); + $session->db->write(q{update userProfileData set publicProfile='none' where publicProfile='0' || publicProfile is NULL || publicProfile=''}); + $session->db->write(q{update userProfileData set publicProfile='all' where publicProfile='1'}); + $session->db->write(q{REPLACE INTO `userProfileField` VALUES ('publicProfile','WebGUI::International::get(861)',1,0,'RadioList','{ all=>WebGUI::International::get(\'public label\',\'Account_Profile\'), friends=>WebGUI::International::get(\'friends only label\',\'Account_Profile\'), none=>WebGUI::International::get(\'private label\',\'Account_Profile\')}','[\"none\"]',8,'4',1,1,0,0,0,'')}); + + #Clean up old templates and settings + my $oldtemplates = { + editUserProfileTemplate => 'Operation/Profile/Edit', + viewUserProfileTemplate => 'Operation/Profile/View', + manageFriendsTemplateId => 'friends/manage', + sendPrivateMessageTemplateId => 'Inbox/SendPrivateMessage', + viewInboxTemplateId => 'Inbox', + viewInboxMessageTemplateId => 'Inbox/Message', + }; + + foreach my $setting (keys %{$oldtemplates}) { + #Remove the setting + $session->db->write("delete from settings where name=?",[$setting]); + #Remove all the templates with the related namespace + my $assets = $session->db->buildArrayRef("select distinct assetId from template where namespace=?",[$oldtemplates->{$setting}]); + #Purge the template + foreach my $assetId (@{$assets}) { + WebGUI::Asset->newByDynamicClass($session,$assetId)->purge; + } + } + + print "DONE!\n" unless $quiet; +} + # -------------- DO NOT EDIT BELOW THIS LINE -------------------------------- #---------------------------------------------------------------------------- diff --git a/etc/WebGUI.conf.original b/etc/WebGUI.conf.original index 29d85ec97..315c7b6dd 100644 --- a/etc/WebGUI.conf.original +++ b/etc/WebGUI.conf.original @@ -609,7 +609,64 @@ "category" : "utilities" } }, - + +# +# Specify the list of account pluggins available on your site. +# Account pluggins are returned on the site in the order they are list in the config file +# Each pluggin has serveral properties +# +# identifier - This string will act as the identifying agent for this account pluggin. It is passed along + the url and cannot contain spaces. +# title - The title of the module which is displayed on the website. +# className - The class which drives this module + +# +# IMPORTANT NOTE - PLEASE READ: +# +# DO NOT DELETE THE WebGUI::Account::User pluggin from this list. This module +# is Deprecated on release and is mandatory for every site. You may move it's position +# but if you remove it you will break WebGUI's Authentication System. This module will +# be replaced in WebGUI 8 once the APIs can be broken and the Account portion of Auth +# can be moved into the Account system +# +# A profile module is required as well. You may replace the default profile +# module with a custom version, but many systems in WebGUI rely on being +# able to display a user's profile. +# + +"account" : [ + { + identifier : "profile", + title : "^International(title,Account_Profile);", + className : "WebGUI::Account::Profile" + }, + { + identifier : "inbox", + title : "^International(title,Account_Inbox);", + className : "WebGUI::Account::Inbox" + }, + { + identifier : "friends", + title : "^International(title,Account_Friends);", + className : "WebGUI::Account::Friends" + }, + { + identifier : "shop", + title : "^International(title,Account_Shop);", + className : "WebGUI::Account::Shop" + }, + { + identifier : "user", + title : "^International(title,Account_User);", + className : "WebGUI::Account::User" + }, +], + +# Specify which of the modules in the above list is used +# to display the user's profile. This is a mandatory configuration + +"profileModuleIdentifier" : "profile", + # Optionally add a "Save and Commit" button to assets so that you # don't have to hit "Commit My Changes" seperately. diff --git a/lib/WebGUI/Account.pm b/lib/WebGUI/Account.pm new file mode 100644 index 000000000..09b9814ea --- /dev/null +++ b/lib/WebGUI/Account.pm @@ -0,0 +1,517 @@ +package WebGUI::Account; + +use strict; + +use Class::InsideOut qw{ :std }; +use WebGUI::Exception; +use Carp qw(croak); +use WebGUI::International; +use WebGUI::Pluggable; +use WebGUI::Utility; + +=head1 NAME + +Package WebGUI::Account::Profile + +=head1 DESCRIPTION + +This is the class which is used to display a users's profile information + +=head1 SYNOPSIS + + use base 'WebGUI::Account'; + + currentState("edit"); + +=head1 METHODS + +These subroutines are available from this package: + +=cut + +readonly session => my %session; +readonly module => my %module; +public method => my %method; +public uid => my %uid; +public store => my %store; #This is an all purpose hash to store stuff in: $store{id $self}->{something} = "something" + +#------------------------------------------------------------------- + +=head2 appendAccountLinks ( session , var) + + Class method which appends common links to preform various account tasks + +=head3 session + + WebGUI::Session object + +=head3 var + + hash ref to append template variables to + +=cut + +sub appendAccountLinks { + my $class = shift; + my $session = shift; + my $var = shift; + + return unless $var; + + my $i18n = WebGUI::International->new($session); + my $format = q{%s}; + my @array = (); + + #Turn Admin On + if ($session->user->isInGroup(12)) { + if ($session->var->isAdminOn) { + $var->{'admin_mode_url' } = $session->url->page('op=switchOffAdmin'); + $var->{'admin_mode_text'} = $i18n->get(12); + } + else { + $var->{'admin_mode_url' } = $session->url->page('op=switchOnAdmin'); + $var->{'admin_mode_text'} = $i18n->get(63); + } + push(@array,{ + 'options.display' => sprintf($format,$var->{'admin_mode_url'},$var->{'admin_mode_text'}) + }); + } + + #Pluggin - delete eventually + push(@array, {'options.display' => ''.$i18n->get('my purchases', 'Shop').''}); + + #Pluggin - delete eventually + if ($session->setting->get('userInvitationsEnabled')) { + push @array, { + 'options.display' => sprintf('%s', $session->url->page('op=inviteUser'), $i18n->get('invite a friend')), + }; + } + + #Logout + $var->{'logout_url' } = $session->url->page('op=auth;method=logout'); + $var->{'logout_text'} = $i18n->get(64); + push(@array,{ + 'options.display' => sprintf($format,$var->{'logout_url'},$var->{'logout_text'}) + }); + + #Deactivate Account + if ($session->setting->get("selfDeactivation") && !$session->user->isAdmin){ + $var->{'self_deactivation_url' } = $session->url->page('op=auth;method=deactivateAccount'); + $var->{'self_deactivation_text'} = $i18n->get(65); + push(@array,{ + 'options.display' => sprintf($format,$var->{'self_deactivation_url' },$var->{'self_deactivation_text'}) + }); + } + + #Return to site + $var->{'return_to_site_url' } = $session->url->getBackToSiteURL; + $var->{'return_to_site_link'} = $i18n->get(493); + push(@array,{ + 'options.display' => sprintf($format,$var->{'return_to_site_url'},$var->{'return_to_site_link'}) + }); + + $var->{'account.options'} = \@array; +} + + +#------------------------------------------------------------------- + +=head2 appendCommonVars ( var ) + + Appends common template variables that all most templates will 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; + + $var->{'user_full_name' } = $user->getWholeName; + $var->{'user_member_since' } = $user->dateCreated; + $var->{'view_profile_url' } = $user->getProfileUrl; + $var->{'gateway_url' } = $session->url->page("op=account"); + $var->{'back_url' } = $session->env->get("HTTP_REFERER") || $var->{'view_profile_url'} +} + + +#------------------------------------------------------------------- + +=head2 callMethod ( [ method, args, uid ] ) + +Calls the method passed in + +=method + +Method to call. If no method is passed in, the view method is called + +=args + +array reference of arguments to pass to the method being called. + +=uid + +uid to set in the object. + +=cut + +sub callMethod { + my $self = shift; + my $method = shift || "view"; + my $args = shift; + my $uid = shift; + + my $module = $self->module; + + #Set the method in the object + $self->method($method); + #Set the uid in the object + $self->uid($uid); + + $method = "www_".$method; + + unless ($self->can($method)) { + WebGUI::Error::MethodNotFound->throw( + error => qq{Could not locate method $method in the $module module of the account system}, + method => $method + ); + return undef; + } + + #Try to call the method + my $output = eval { $self->$method(@{$args}) }; + + #Croak on error + if($@) { + croak "Unable to run $method on $module: $@"; + return undef; + } + + #Return the output from the method call + return $output; +} + +#------------------------------------------------------------------- + +=head2 displayContent ( content[, withoutStyle] ) + +Wraps the content in the style and layout of the account pluggin + +=content + +Content to wrap in the pluggin style and layout + +=withoutStyle + +Return the layout without the style wrapper + +=cut + +sub displayContent { + my $self = shift; + my $content = shift; + my $noStyle = shift; + my $session = $self->session; + + #Wrap content into the layout + my $var = {}; + $var->{content} = $content; + + my $configs = $session->config->get("account"); + my $method = $self->method || "view"; + + # Get fieldsets for avaiable account methods in the order they exist in the config file and append them to the template + my @pluggins = (); + foreach my $account (@{$configs}) { + #Instantiate the pluggin + my $instance = undef; + my $identifier = $account->{identifier}; + #Use the currently instantiated pluggin if we are checking this pluggin + if($account->{identifier} eq $self->module) { + $instance = $self; + } + else { + #Eval it as we don't want to fail if there's a problem with another method in the config file + $instance = eval { WebGUI::Content::Account->createInstance($session,$identifier) }; + if (my $e = WebGUI::Error->caught) { + $session->log->warn("Couldn't instantiate Account Pluggin ".$account->{className}." ... skipping"); + next; + } + elsif(!$instance->isa('WebGUI::Account')) { + $session->log->warn((ref $instance)." is not a subclass of WebGUI::Account ... skipping"); + next; + } + #Set the current uid state in the instance + $instance->uid($self->uid); + } + + #Skip this module if the user can't view it + next unless ($instance->canView); + + #Push the tab variables onto the template + my %hash = %{$account}; + my $identifier = $account->{identifier}; + + $hash{'is_'.$identifier } = "true"; + $hash{'is_method_'.$self->method } = "true"; + $hash{'url' } = $instance->getUrl("module=$identifier",1); + $hash{'isActive' } = "true" if($identifier eq $self->module); + WebGUI::Macro::process(\$hash{'title'}); + push(@pluggins,\%hash); + + #Append common display variables to the main template + $instance->appendCommonVars($var); + } + $var->{'account_loop'} = \@pluggins; + + #Process the layout template + my $output = $self->processTemplate($var,$self->getLayoutTemplateId); + + return $output if($noStyle); + #Wrap the layout in the user style + $session->http->setCacheControl("none"); + return $session->style->process($output,$self->getStyleTemplateId); +} + + +#------------------------------------------------------------------- + +=head2 canView ( ) + + Override this method to create permission levels for your Account Pluggin + +=cut + +sub canView { + my $self = shift; + return 1; +} + +#------------------------------------------------------------------- + +=head2 editSettingsForm ( ) + + Override this method to create settings for your Account Pluggin + +=cut + +sub editSettingsForm { + my $self = shift; + return ""; +} + +#------------------------------------------------------------------- + +=head2 editSettingsFormSave ( ) + + Override this method to create settings for your Account Pluggin + +=cut + +sub editSettingsFormSave { + my $self = shift; + return ""; +} + +#------------------------------------------------------------------- + +=head2 getLayoutTemplateId ( ) + + Override this method to return the template Id for the account layout. + +=cut + +sub getLayoutTemplateId { + my $self = shift; + return "N716tpSna0iIQTKxS4gTWA"; +} + +#------------------------------------------------------------------- + +=head2 getStyleTemplate ( ) + + Override this method to return the template for the main style. + +=cut + +sub getStyleTemplateId { + my $self = shift; + 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=}.$self->module.q{;do=}.$self->method; + } + + my $uid = $self->uid; + $pairs .= ";uid=".$uid if($appendUID && $uid); + + return $session->url->page($pairs); +} + +#------------------------------------------------------------------- + +=head2 new ( session, module [,method ,uid] ) + +Constructor. + +=head3 $session + +A WebGUI::Session object. + +=head3 module + +The module being called + +=cut + +sub new { + my $class = shift; + my $session = shift; + my $module = shift; + + unless (ref $session eq 'WebGUI::Session') { + WebGUI::Error::InvalidObject->throw( + expected =>"WebGUI::Session", + got =>(ref $session), + error => q{Must provide a session variable} + ); + } + + my $self = register $class; + my $id = id $self; + + $session { $id } = $session; + $module { $id } = $module; + $store { $id } = {}; + $method { $id } = "view"; + $uid { $id } = undef; + + return $self; +} + +#------------------------------------------------------------------- + +=head2 processTemplate ( vars, templateId, template ) + +Returns the content generated from this template. It adds the Asset control +bar to the template variables, as well as all Asset properties and metadata. + +=head3 vars + +A hash reference containing variables and loops to pass to the template engine. + +=head3 templateId + +An id referring to a particular template in the templates table. + +=head3 template + +Instead of passing in a templateId, you may pass in a template object. + +=cut + +sub processTemplate { + my $self = shift; + my $session = $self->session; + + my $var = shift; + my $templateId = shift; + my $template = shift; + my $className = ref $self; + + # Sanity checks + if (ref $var ne "HASH") { + $session->log->error("First argument to processTemplate() should be a hash reference."); + my $i18n = WebGUI::International->new($session, 'Account'); + return sprintf($i18n->get('Error: Cannot instantiate template'),$templateId,$className); + } + + $template = WebGUI::Asset->new($session, $templateId,"WebGUI::Asset::Template") unless (defined $template); + + unless (defined $template) { + $session->log->error("Can't instantiate template $templateId for class ".$className); + my $i18n = WebGUI::International->new($session, 'Account'); + return sprintf($i18n->get('Error: Cannot instantiate template'),$templateId,$className); + } + + return $template->process($var); +} + + +#------------------------------------------------------------------- + +=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 new file mode 100644 index 000000000..68ecf8d89 --- /dev/null +++ b/lib/WebGUI/Account/Friends.pm @@ -0,0 +1,588 @@ +package WebGUI::Account::Friends; + +use strict; + +use WebGUI::Exception; +use WebGUI::International; +use WebGUI::Pluggable; +use WebGUI::Utility; +use base qw/WebGUI::Account/; + +=head1 NAME + +Package WebGUI::Account::Friends + +=head1 DESCRIPTION + +This is the class which is used to display a users's friends + +=head1 SYNOPSIS + + use WebGUI::Account::Friends; + +=head1 METHODS + +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' } = $session->url->page("op=account"); + $var->{'back_url' } = $session->env->get("HTTP_REFERER") || $var->{'view_profile_url'} +} + +#------------------------------------------------------------------- + +=head2 canView ( ) + + Whether or not the current user can view this user's friends + +=cut + +sub canView { + my $self = shift; + my $session = $self->session; + my $uid = $self->uid; + + return 1 if (($session->user->userId eq $uid || $uid eq "") && $session->user->profileField('ableToBeFriend')); + + my $user = WebGUI::User->new($session,$uid); + return 0 if($user->isVisitor); #This should never happen but let's make sure + return 0 unless ($user->profileField('ableToBeFriend')); #User doesn't have friends enabled + return WebGUI::User->new($session,$uid)->profileIsViewable($session->user); #User's profile isn't viewable by this user +} + +#------------------------------------------------------------------- + +=head2 editSettingsForm ( ) + + Creates form elements for user settings page custom to this account module + +=cut + +sub editSettingsForm { + my $self = shift; + my $session = $self->session; + my $i18n = WebGUI::International->new($session,'Account_Friends'); + my $f = WebGUI::HTMLForm->new($session); + + $f->template( + name => "friendsStyleTemplateId", + value => $self->getStyleTemplateId, + namespace => "style", + label => $i18n->get("friends style template label"), + hoverHelp => $i18n->get("friends style template hoverHelp") + ); + $f->template( + name => "friendsLayoutTempalteId", + value => $self->getLayoutTemplateId, + namespace => "Account/Layout", + label => $i18n->get("friends layout template label"), + hoverHelp => $i18n->get("friends layout template hoverHelp") + ); + $f->template( + name => "friendsViewTemplateId", + value => $self->getViewTemplateId, + namespace => "Account/Friends/View", + label => $i18n->get("friends view template label"), + hoverHelp => $i18n->get("friends view template hoverHelp") + ); + $f->template( + name => "friendsEditTemplateId", + value => $self->getEditTemplateId, + namespace => "Account/Friends/Edit", + label => $i18n->get("friends edit template label"), + hoverHelp => $i18n->get("friends edit template hoverHelp") + ); + $f->template( + name => "friendsSendRequestTemplateId", + value => $self->getSendRequestTemplateId, + namespace => "Account/Friends/SendRequest", + label => $i18n->get("friends send request template label"), + hoverHelp => $i18n->get("friends send request template hoverHelp") + ); + + $f->template( + name => "friendsErrorTemplateId", + value => $self->getErrorTemplateId, + namespace => "Account/Friends/Error", + label => $i18n->get("friends error template label"), + hoverHelp => $i18n->get("friends error template hoverHelp") + ); + + $f->template( + name => "friendsConfirmTemplateId", + value => $self->getConfirmTemplateId, + namespace => "Account/Friends/Confirm", + label => $i18n->get("friends confirm template label"), + hoverHelp => $i18n->get("friends confirm template hoverHelp") + ); + + $f->template( + name => "friendsRemoveConfirmTemplateId", + value => $self->getRemoveConfirmTemplateId, + namespace => "Account/Friends/Confirm", + label => $i18n->get("friends remove confirm template label"), + hoverHelp => $i18n->get("friends remove confirm template hoverHelp") + ); + + return $f->printRowsOnly; +} + +#------------------------------------------------------------------- + +=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("friendsStyleTemplateId", $form->process("friendsStyleTemplateId","template")); + $setting->set("friendsLayoutTempalteId", $form->process("friendsLayoutTempalteId","template")); + $setting->set("friendsViewTemplateId", $form->process("friendsViewTemplateId","template")); + $session->set("friendsEditTemplateId",$form->process("friendsEditTemplateId","template")); + $session->set("friendsSendRequestTemplateId",$form->process("friendsSendRequestTemplateId","template")); + $session->set("friendsErrorTemplateId",$form->process("friendsErrorTemplateId","template")); + $session->set("friendsConfirmTemplateId",$form->process("friendsConfirmTemplateId","template")); + $session->set("friendsRemoveConfirmTemplateId",$form->process("friendsRemoveConfirmTemplateId","template")); + +} + +#------------------------------------------------------------------- + +=head2 getConfirmTemplateId ( ) + +This method returns the template ID for the confirmation screen. + +=cut + +sub getConfirmTemplateId { + my $self = shift; + return $self->session->setting->get("friendsConfirmTemplateId") || "K8F0j_cq_jgo8dvWY_26Ag"; +} + + +#------------------------------------------------------------------- + +=head2 getEditTemplateId ( ) + +This method returns the template ID for editing friends. + +=cut + +sub getEditTemplateId { + my $self = shift; + return $self->session->setting->get("friendsEditTemplateId") || "AZFU33p0jpPJ-E6qLSWZng"; +} + +#------------------------------------------------------------------- + +=head2 getErrorTemplateId ( ) + +This method returns the template ID for displaying errors. + +=cut + +sub getErrorTemplateId { + my $self = shift; + return $self->session->setting->get("friendsErrorTemplateId") || "7Ijdd8SW32lVgg2H8R-Aqw"; +} + +#------------------------------------------------------------------- + +=head2 getLayoutTemplateId ( ) + +This method returns the template ID for the account layout. + +=cut + +sub getLayoutTemplateId { + my $self = shift; + return $self->session->setting->get("friendsLayoutTempalteId") || $self->SUPER::getLayoutTemplateId; +} + + +#------------------------------------------------------------------- + +=head2 getConfirmTemplateId ( ) + +This method returns the template ID for the confirmation screen. + +=cut + +sub getRemoveConfirmTemplateId { + my $self = shift; + return $self->session->setting->get("friendsRemoveConfirmTemplateId") || "G5V6neXIDiFXN05oL-U3AQ"; +} + + +#------------------------------------------------------------------- + +=head2 getSendRequestTemplateId ( ) + +This method returns the template ID for the send request page. + +=cut + +sub getSendRequestTemplateId { + my $self = shift; + return $self->session->setting->get("friendsSendRequestTemplateId") || "AGJBGviWGAwjnwziiPjvDg"; +} + +#------------------------------------------------------------------- + +=head2 getStyleTemplateId ( ) + +This method returns the template ID for the main style. + +=cut + +sub getStyleTemplateId { + my $self = shift; + return $self->session->setting->get("friendsStyleTemplateId") || $self->SUPER::getStyleTemplateId; +} + +#------------------------------------------------------------------- + +=head2 getViewTemplateId ( ) + +This method returns the template ID for the main view. + +=cut + +sub getViewTemplateId { + my $self = shift; + return $self->session->setting->get("friendsViewTemplateId") || "1Yn_zE_dSiNuaBGNLPbxtw"; +} + + +#------------------------------------------------------------------- + +=head2 www_removeFriend ( ) + +This is a confirmation page of whether or not the user wishes to remove the selected user from friend + +=cut + +sub www_removeFriend { + my $self = shift; + my $session = $self->session; + my $friendId = $session->form->get("friendId"); + my $var = {}; + + $self->appendCommonVars($var); + my $friend = WebGUI::Friends->new($session); + + my $errorMsg = ""; + if (!$friendId) { + my $i18n = WebGUI::International->new($session,"Account_Friends"); + $errorMsg = $i18n->get("no friend selected"); + } + elsif(!$friend->isFriend($friendId)){ + my $i18n = WebGUI::International->new($session,"Account_Friends"); + $errorMsg = $i18n->get("not a friend error"); + } + + if($errorMsg ne "") { + my $backUrl = $self->getUrl("module=friends"); + return $self->showError($var,$errorMsg,$backUrl,$self->getErrorTemplateId); + } + + my $user = WebGUI::User->new($session,$friendId); + $var->{'user_full_name'} = $user->getWholeName; + + $var->{'yes_url' } = $self->getUrl("module=friends;do=removeFriendConfirm;friendId=".$friendId); + $var->{'no_url' } = $self->getUrl("module=friends"); + + return $self->processTemplate($var,$self->getRemoveConfirmTemplateId); +} + + +#------------------------------------------------------------------- + +=head2 www_removeFriend ( ) + +This is a confirmation page of whether or not the user wishes to remove the selected user from friend + +=cut + +sub www_removeFriendConfirm { + my $self = shift; + my $session = $self->session; + my $friendId = $session->form->get("friendId"); + my $var = {}; + my $i18n = WebGUI::International->new($session,"Account_Friends"); + + + $self->appendCommonVars($var); + my $friend = WebGUI::Friends->new($session); + + my $errorMsg = ""; + if (!$friendId) { + $errorMsg = $i18n->get("no friend selected"); + } + elsif(!$friend->isFriend($friendId)){ + $errorMsg = $i18n->get("not a friend error"); + } + + if($errorMsg ne "") { + my $backUrl = $self->getUrl("module=friends"); + return $self->showError($var,$errorMsg,$backUrl,$self->getErrorTemplateId); + } + + my $user = WebGUI::User->new($session,$friendId); + my $msg = sprintf($i18n->get("friend removed"),$user->getWholeName); + + $friend->delete([$friendId]); + + return $self->www_view($msg); + +} + +#------------------------------------------------------------------- + +=head2 www_sendFriendsRequest ( ) + +The page which allows users to submit friends requests. + +=cut + +sub www_sendFriendsRequest { + my $self = shift; + my $session = $self->session; + my $var = {}; + my $uid = $self->uid; + + my $user = WebGUI::User->new($session,$uid); + my $i18n = WebGUI::International->new($session,'Account_Friends'); + + unless ($user->acceptsFriendsRequests($session->user)) { + my $errorMsg = $i18n->get('does not want to be a friend'); + my $friend = WebGUI::Friends->new($session); + if($friend->isFriend($uid)) { + $errorMsg = $i18n->get("error user is already friend"); + } + elsif($friend->isInvited($uid)) { + $errorMsg = $i18n->get("error user is already invited"); + } + return $self->showError($var,$errorMsg,$session->user->getProfileUrl,$self->getErrorTemplateId); + } + + $self->appendCommonVars($var); + + #Overwrite these + $var->{'user_full_name' } = $user->getWholeName; + $var->{'user_member_since' } = $user->dateCreated; + + my $defaultComment = sprintf( + $i18n->get('default friend comments'), + $user->getFirstName, + $session->user->getFirstName + ); + $var->{'form_message_text'} = WebGUI::Form::textarea($session, { + name =>"message", + value =>$defaultComment, + width =>600, + height =>200 + }); + + $var->{'form_message_rich'} = WebGUI::Form::HTMLArea($session, { + name => "message", + value => $defaultComment, + width => "600", + }); + + $var->{'form_header' } = WebGUI::Form::formHeader($session,{ + action => $self->getUrl("module=friends;do=sendFriendsRequestSave;uid=$uid"), + extras => q{name="messageForm"} + }); + + $var->{'submit_button' } = WebGUI::Form::submit($session,{}); + $var->{'form_footer' } = WebGUI::Form::formFooter($session, {}); + + $var->{'cancel_url' } = $user->getProfileUrl; + + return $self->processTemplate($var,$self->getSendRequestTemplateId); +} + + +#------------------------------------------------------------------- + +=head2 www_sendFriendsRequestSave ( ) + +This method allows users to save friends requests + +=cut + +sub www_sendFriendsRequestSave { + my $self = shift; + my $session = $self->session; + my $var = {}; + my $uid = $self->uid; + + my $user = WebGUI::User->new($session,$uid); + + #Errors fall through to the view page. + unless ($user->acceptsFriendsRequests($session->user)) { + return $self->www_sendFriendsRequest; + } + + my $inboxUrl = WebGUI::Account::Inbox->getViewInvitationUrl($session); + my $friends = WebGUI::Friends->new($session); + $friends->sendAddRequest($uid, $session->form->get('message'),$inboxUrl); + + $self->appendCommonVars($var); + + #Overwrite this + $var->{'user_full_name' } = $user->getWholeName; + $var->{'user_profile_url' } = $user->getProfileUrl; + + return $self->processTemplate($var,$self->getConfirmTemplateId); + +} + +#------------------------------------------------------------------- + +=head2 www_view ( ) + +The main view page for editing your friends. + +=cut + +sub www_view { + my $self = shift; + my $msg = shift; + my $session = $self->session; + my $var = {}; + + my $uid = $self->uid; + my $user = ($uid) ? WebGUI::User->new($session,$uid) : $session->user; + + $self->appendCommonVars($var); + + my $displayView = $uid ne ""; + $var->{'can_edit' } = $session->user->userId eq $user->userId; + $var->{'display_message'} = $msg; + + #Override these + $var->{'user_full_name' } = $user->getWholeName; + $var->{'user_member_since' } = $user->dateCreated; + + unless ($user->profileField('ableToBeFriend') && $user->profileIsViewable($session->user)) { + my $i18n = WebGUI::International->new($session,"Account_Friends"); + my $errorMsg = ""; + if($var->{'can_edit'}) { + $errorMsg = $i18n->get("friends is off"); + } + else { + $errorMsg = $i18n->get("no access"); + } + my $backUrl = $self->getUrl("op=account"); + return $self->showError($var,$errorMsg,$backUrl,$self->getErrorTemplateId); + } + + #Deal with rows per page + my $rpp = $session->form->get("rpp") || 25; + my $rpp_url = ";rpp=$rpp"; + + #Cache the base url + my $friendsUrl = $self->getUrl("op=account;module=friends;do=view"); + + #Note for anyone who attempts to sort this list by the user's whole name: + #You can do this, but the only way to do it efficiently is to join + #the users, userProfileData, and groupings table. This will break if the groups API + #changes in WebGUI 8, so we decided to leave it sorted by username only. + + #Create the paginator + my $friends = $user->friends->getUserList(1); + my @friendIds = keys %{$friends}; + my $p = WebGUI::Paginator->new( + $session, + $friendsUrl.$rpp_url, + $rpp + ); + $p->setDataByArrayRef(\@friendIds); + + #Export page to template + my @friends = (); + foreach my $friendId ( @{$p->getPageData} ) { + my $friend = WebGUI::User->new($session,$friendId); + next if($friend->isVisitor); + #If you have friends turned off you shouldn't show up when other people view your friends friends + next if($displayView && !$friend->profileField('ableToBeFriend')); + + my $hash = {}; + $hash->{'friend_full_name' } = $friend->getWholeName; + $hash->{'isViewable' } = $friend->profileIsViewable; + $hash->{'friend_id' } = $friend->userId; + $hash->{'friend_member_since' } = $friend->dateCreated; + $hash->{'friend_member_since_human'} = $session->datetime->epochToHuman($friend->dateCreated); + $hash->{'friend_isOnline' } = $friend->isOnline; + if($hash->{'isViewable'}) { + $hash->{'friend_profile_url'} = $friend->getProfileUrl; + if($friend->profileField("photo")) { + my $store = WebGUI::Storage::Image->get($session,$friend->profileField("photo")); + my $file = $store->getFiles->[0]; + $hash->{'friend_photo_url' } = $store->getUrl($file); + $hash->{'friend_photo_url_thumb'} = $store->getThumbnailUrl($file); + } + } + + $hash->{'acceptsPrivateMessages'} = $friend->acceptsPrivateMessages($session->user->userId); + if ($displayView) { + if($friend->acceptsFriendsRequests($session->user)) { + $hash->{'friend_request_url'} = $self->getUrl("module=friends;do=sendFriendsRequest;uid=".$friend->userId); + } + } + else { + $hash->{'remove_url'} = $self->getUrl("module=friends;do=removeFriend;friendId=".$friend->userId); + } + push(@friends,$hash); + } + my $friendCount = $p->getRowCount; + + $var->{'friends_loop' } = \@friends; + $var->{'has_friends' } = $friendCount > 0; + $var->{'friends_total' } = $friendCount; + + 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='}.$friendsUrl.q{;rpp='+this.options[this.selectedIndex].value"} + }); + + my $templateId = ($displayView) ? $self->getViewTemplateId : $self->getEditTemplateId; + return $self->processTemplate($var,$templateId); +} + +1; diff --git a/lib/WebGUI/Account/Inbox.pm b/lib/WebGUI/Account/Inbox.pm new file mode 100644 index 000000000..f5b2fa181 --- /dev/null +++ b/lib/WebGUI/Account/Inbox.pm @@ -0,0 +1,1144 @@ +package WebGUI::Account::Inbox; + +use strict; + +use WebGUI::Form; +use WebGUI::Exception; +use WebGUI::International; +use WebGUI::Pluggable; +use WebGUI::Utility; +use base qw/WebGUI::Account/; + +=head1 NAME + +Package WebGUI::Account::Inbox + +=head1 DESCRIPTION + +This is the class which is used to display a users's inbox + +=head1 SYNOPSIS + + use WebGUI::Account::Inbox; + +=head1 METHODS + +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 $session = $self->session; + my $var = shift; + my $inbox = shift || WebGUI::Inbox->new($session); + my $user = $session->user; + + $self->SUPER::appendCommonVars($var); + + $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; + $var->{'invitation_count' } = $self->getInvitationCount; + $var->{'invitations_enabled' } = $session->user->profileField('ableToBeFriend'); + +} + +#------------------------------------------------------------------- + +=head2 canView ( ) + + Returns whether or not the user can view the inbox tab + +=cut + +sub canView { + my $self = shift; + return ($self->uid eq ""); +} + +#------------------------------------------------------------------- + +=head2 editSettingsForm ( ) + + Creates form elements for user settings page custom to this account module + +=cut + +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 => "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 => "inboxViewInvitationTemplateId", + value => $self->getViewInvitationTemplateId, + namespace => "Account/Inbox/ViewInvitation", + label => $i18n->get("inbox view invitation template label"), + hoverHelp => $i18n->get("inbox view invitation template hoverHelp") + ); + $f->template( + name => "inboxInvitationConfirmTemplateId", + value => $self->getInvitationConfirmTemplateId, + namespace => "Account/Inbox/Confirm", + label => $i18n->get("invitation confirm message template label"), + hoverHelp => $i18n->get("invitation confirm message template hoverHelp") + ); + + return $f->printRowsOnly; +} + +#------------------------------------------------------------------- + +=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; + + #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("inboxViewInvitationTemplateId",$form->process("inboxViewInvitationTemplateId","template")); + $session->set("inboxInvitationConfirmTemplateId",$form->process("inboxInvitationConfirmTemplateId","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 getInvitationCount ( ) + +This method returns the total number of invitations in the invitation box. + +=cut + +sub getInvitationCount { + my $self = shift; + my $session = $self->session; + return $session->db->quickScalar( + q{select count(*) from friendInvitations where friendId=?}, + [$session->user->userId] + ); +} + +#------------------------------------------------------------------- + +=head2 getInvitationConfirmTemplateId ( ) + +This method returns the template ID for invitation errors. + +=cut + +sub getInvitationConfirmTemplateId { + my $self = shift; + return $self->session->setting->get("inboxInvitationConfirmTemplateId") || "5A8Hd9zXvByTDy4x-H28qw"; +} + + +#------------------------------------------------------------------- + +=head2 getLayoutTemplateId ( ) + +This method returns the template ID for the account layout. + +=cut + +sub getLayoutTemplateId { + my $self = shift; + 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"; +} + +#------------------------------------------------------------------- + +=head2 getStyleTemplateId ( ) + +This method returns the template ID for the main style. + +=cut + +sub getStyleTemplateId { + my $self = shift; + return $self->session->setting->get("inboxStyleTemplateId") || $self->SUPER::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 getViewInvitationTemplateId ( ) + +This method returns the id for the view message template. + +=cut + +sub getViewInvitationTemplateId { + my $self = shift; + return $self->session->setting->get("inboxViewInvitationTemplateId") || "VBkY05f-E3WJS50WpdKd1Q"; +} + +#------------------------------------------------------------------- + +=head2 getViewInvitationUrl ( session ) + +Class method which returns the base url for viewing invitations + +=head3 session + +session object + +=cut + +sub getViewInvitationUrl { + my $class = shift; + my $session = shift; + my $url = $session->url; + + return $url->append($url->getSiteURL,"op=account;module=inbox;do=viewInvitation"); +} + + +#------------------------------------------------------------------- + +=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. + +=cut + +sub getViewTemplateId { + my $self = shift; + return $self->session->setting->get("inboxViewTemplateId") || "c8xrwVuu5QE0XtF9DiVzLw"; +} + +#------------------------------------------------------------------- + +=head2 www_approveDenyInvitations ( ) + +Approves or denies invitations passed in. + +=cut + +sub www_approveDenyInvitations { + my $self = shift; + my $session = $self->session; + my $form = $session->form; + + my @messages = $form->process("inviteId","checkList"); + my $approve = $form->get("accept"); + my $deny = $form->get("deny"); + + my $friends = WebGUI::Friends->new($session); + + my @users = (); + + foreach my $inviteId (@messages) { + my $invite = $friends->getAddRequest($inviteId); + my $inviter = WebGUI::User->new($session, $invite->{inviterId}); + next unless ($invite->{inviterId}); #Not sure how this could ever happen, but check for it + next unless ($session->user->userId eq $invite->{friendId}); #Protect against malicious stuff + if($deny) { + $friends->rejectAddRequest($inviteId); + } + elsif($approve) { + $friends->approveAddRequest($inviteId); + } + push (@users, { + 'friend_name' => $inviter->getWholeName, + 'is_denied' => ($deny ne ""), + 'is_approved' => ($approve ne ""), + }); + } + my $var = {}; + $var->{'friends_loop'} = \@users; + + #Append common vars + $self->appendCommonVars($var,WebGUI::Inbox->new($session)); + + #Return a confirm message + return $self->processTemplate($var,$self->getInvitationConfirmTemplateId); +} + +#------------------------------------------------------------------- + +=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 = {}; + my $i18n = WebGUI::International->new($session,'Account_Inbox'); + + #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("op=account;module=inbox;do=manageInvitations"); + + #Create the paginator + my $sql = q{ select * from friendInvitations where friendId=? order by dateSent desc }; + my $p = WebGUI::Paginator->new( + $session, + $inboxUrl.$rpp_url, + $rpp + ); + $p->setDataByQuery($sql,undef,undef,[$user->userId]); + + #Export page to template + my @msg = (); + foreach my $row ( @{$p->getPageData} ) { + my $inviter = WebGUI::User->new($session,$row->{inviterId}); + next if($inviter->isVisitor); # Inviter account got deleted + + my $epoch = WebGUI::DateTime->new(mysql => $row->{dateSent} )->epoch; + + my $hash = {}; + $hash->{'invite_id' } = $row->{inviteId}; + $hash->{'message_url' } = $self->getUrl("module=inbox;do=viewInvitation;inviteId=".$row->{inviteId}); + $hash->{'from_id' } = $row->{inviterId}; + $hash->{'from_url' } = $inviter->getProfileUrl; #Get the profile url of this user which may be cached. + $hash->{'from' } = $inviter->getWholeName; + $hash->{'dateStamp' } = $epoch; + $hash->{'dateStamp_formatted'} = $session->datetime->epochToHuman($epoch); + $hash->{'form_checkbox' } = WebGUI::Form::checkbox($session,{ + name => "inviteId", + value => $row->{inviteId} + }); + push(@msg,$hash); + } + my $msgCount = $p->getRowCount; + + $var->{'message_loop' } = \@msg; + $var->{'has_messages' } = $msgCount > 0; + $var->{'message_total' } = $msgCount; + + $var->{'form_start' } = WebGUI::Form::formHeader($session,{ + action => $self->getUrl("module=inbox;do=approveDenyInvitations") + }); + $var->{'form_end' } = WebGUI::Form::formFooter($session); + + $var->{'form_accept' } = WebGUI::Form::submit($session,{ + name =>"accept", + value =>$i18n->get("accept button label") + }); + + $var->{'form_deny' } = WebGUI::Form::submit($session,{ + name =>"deny", + value =>$i18n->get("deny button label") + }); + + 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='}.$inboxUrl.q{;rpp='+this.options[this.selectedIndex].value"} + }); + + #Append common vars + $self->appendCommonVars($var,WebGUI::Inbox->new($session)); + #Append pagination vars + $p->appendTemplateVars($var); + + 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) { + $var->{'isInbox'} = "true"; + 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) { + $var->{'isInbox'} = "true"; + 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"); + $var->{'isInbox'} = "true"; + 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'} || "", + width =>600, + height =>200 + }); + + $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 ( ) + +The main view page for editing the user's profile. + +=cut + +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_viewInvitation ( ) + +The page on which users view their messages + +=cut + +sub www_viewInvitation { + my $self = shift; + my $session = $self->session; + my $user = $session->user; + + my $var = {}; + my $inviteId = shift || $session->form->get("inviteId"); + my $errorMsg = shift; + my $i18n = WebGUI::International->new($session,'Account_Inbox'); + + + my $friends = WebGUI::Friends->new($session); + my $invitation = $friends->getAddRequest($inviteId); + my $inviter = WebGUI::User->new($session,$invitation->{inviterId}); + + #Add common template variable for displaying the inbox + $self->appendCommonVars($var,WebGUI::Inbox->new($session)); + + #Handle Errors + if (!($invitation->{inviteId})) { #Invitation is invalid + $errorMsg = $i18n->get("invitation does not exist"); + } + elsif ($inviter->isVisitor) { #Inviter user account was deleted + $errorMsg = $i18n->get("inviter no longer exists"); + } + elsif ($session->user->userId ne $invitation->{friendId}) { #User trying to view someone else's invitation + $errorMsg = $i18n->get("no access to invitation"); + } + + if($errorMsg) { + my $backUrl = $var->{'view_invitations_url'}; + $var->{'isInvitation'} = "true"; + return $self->showError($var,$errorMsg,$backUrl,$self->getInboxErrorTemplateId); + } + + my $epoch = WebGUI::DateTime->new(mysql => $invitation->{dateSent} )->epoch; + + $var->{'invite_id' } = $inviteId; + $var->{'message_from_id' } = $inviter->userId; + $var->{'message_from' } = $inviter->getWholeName; + $var->{'message_from_url' } = $inviter->getProfileUrl; + $var->{'message_dateStamp' } = $epoch; + $var->{'message_dateStamp_human'} = $session->datetime->epochToHuman($epoch); + $var->{'message_body' } = $invitation->{comments}; + + 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; + } + + #Build the action URLs + my $nextInvitation = $friends->getPreviousInvitation($invitation); #Messages sorted descending so next is actually previous + if( $nextInvitation->{inviteId} ) { + $var->{'hasNext' } = "true"; + $var->{'next_message_url'} = $self->getUrl("module=inbox;do=viewInvitation;inviteId=".$nextInvitation->{inviteId}); + } + + my $prevInvitation = $friends->getNextInvitation($invitation); #Messages sorted descending so previous is actually next + if( $prevInvitation->{inviteId} ) { + $var->{'hasPrevious' } = "true"; + $var->{'prev_message_url'} = $self->getUrl("module=inbox;do=viewInvitation;inviteId=".$prevInvitation->{inviteId}); + } + + $var->{'form_header' } = WebGUI::Form::formHeader($session,{ + action => $self->getUrl("module=inbox;do=approveDenyInvitations;inviteId=".$inviteId) + }); + $var->{'form_footer' } = WebGUI::Form::formFooter($session); + + $var->{'form_accept' } = WebGUI::Form::submit($session,{ + name =>"accept", + value =>$i18n->get("accept button label") + }); + + $var->{'form_deny' } = WebGUI::Form::submit($session,{ + name =>"deny", + value =>$i18n->get("deny button label") + }); + + return $self->processTemplate($var,$self->getViewInvitationTemplateId); +} + +#------------------------------------------------------------------- + +=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'}; + $var->{'isInvitation'} = "true"; + 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_dateStamp_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->getPreviousMessage($message); #Message are displayed in descending order so next is actually previous + if( defined $nextMessage ) { + $var->{'hasNext' } = "true"; + $var->{'next_message_url'} = $self->getUrl("module=inbox;do=viewMessage;messageId=".$nextMessage->getId); + } + + my $prevMessage = $inbox->getNextMessage($message); #Messages are displayed in descending order so previous is actually next + 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 new file mode 100644 index 000000000..ba14b5670 --- /dev/null +++ b/lib/WebGUI/Account/Profile.pm @@ -0,0 +1,491 @@ +package WebGUI::Account::Profile; + +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/; + +=head1 NAME + +Package WebGUI::Account::Profile + +=head1 DESCRIPTION + +This is the class which is used to display a users's profile information + +=head1 SYNOPSIS + + use WebGUI::Account::Profile; + +=head1 METHODS + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 appendCommonVars ( var ) + + Appends common template variables that all profile 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'}; + $var->{'invitations_enabled' } = $session->user->profileField('ableToBeFriend'); +} + +#------------------------------------------------------------------- + +=head2 editSettingsForm ( ) + + Creates form elements for user settings page custom to this account module + +=cut + +sub editSettingsForm { + my $self = shift; + my $session = $self->session; + my $setting = $session->setting; + my $i18n = WebGUI::International->new($session,'Account_Profile'); + 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 => "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 => "profileErrorTemplateId", + value => $self->getErrorTemplateId, + namespace => "Account/Profile/Error", + label => $i18n->get("profile error template label"), + hoverHelp => $i18n->get("profile error template hoverHelp") + ); + + + return $f->printRowsOnly; +} + + +#------------------------------------------------------------------- + +=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")); + $setting->set("profileErrorTemplateId",$form->process("profileErrorTemplateId","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 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("profileEditTemplateId") || "75CmQgpcCSkdsL-oawdn3Q"; +} + +#------------------------------------------------------------------- + +=head2 getErrorTemplateId ( ) + +This method returns the template ID used to display the error page. + +=cut + +sub getErrorTemplateId { + my $self = shift; + return $self->session->setting->get("profileErrorTemplateId") || "MBmWlA_YEA2I6D29OMGtRg"; +} + + +#------------------------------------------------------------------- + +=head2 getLayoutTemplateId ( ) + +This method returns the template ID for the account layout. + +=cut + +sub getLayoutTemplateId { + my $self = shift; + my $session = $self->session; + my $method = $self->method; + my $uid = $self->uid; + + return $self->getEditLayoutTemplateId if($method eq "edit" || $uid eq ""); + return $session->setting->get("profileLayoutTemplateId") || $self->SUPER::getLayoutTemplateId; +} + +#------------------------------------------------------------------- + +=head2 getStyleTemplateId ( ) + +This method returns the template ID for the main style. + +=cut + +sub getStyleTemplateId { + my $self = shift; + return $self->session->setting->get("profileStyleTemplateId") || $self->SUPER::getStyleTemplateId; +} + +#------------------------------------------------------------------- + +=head2 getViewTemplateId ( ) + +This method returns the template ID for the view profile page. + +=cut + +sub getViewTemplateId { + my $self = shift; + return $self->session->setting->get("profileViewTemplateId") || "2CS-BErrjMmESOtGT90qOg"; +} + +#------------------------------------------------------------------- + +=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); + + $var->{'profile_errors' } = []; + map{ push(@{$var->{'profile_errors'}},{ error_message => $_ }) } @{$errors->{errors}} if($hasErrors); + $var->{'hasErrors' } = scalar(@{$var->{'profile_errors'}}) > 0; + + 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, + 'profile_errors' => $var->{'profile_errors'}, + }); + #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); + + $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 = $session->user->validateProfileDataFromForm($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 display page of the . + +=cut + +sub www_view { + my $self = shift; + my $session = $self->session; + my $var = {}; + my $uid = $self->uid; + my $selected = $session->form->get("selected"); #Allow users to template tabs or other category dividers + + 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); + + $self->appendCommonVars($var); + + #Overwrite these + $var->{'user_full_name' } = $user->getWholeName; + $var->{'user_member_since' } = $user->dateCreated; + + #Check user privileges + unless ($user->profileIsViewable($session->user)) { + my $i18n = WebGUI::International->new($session,'Account_Profile'); + return $self->showError( + $var, + $i18n->get("profile not public error"), + $var->{'back_url'}, + $self->getErrorTemplateId + ); + } + + 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); + my $privacySetting = $user->profileField("publicProfile") || "none"; + $var->{'profile_privacy_'.$privacySetting } = "true"; + + $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); + + return $self->processTemplate($var,$self->getViewTemplateId); +} + + + +1; diff --git a/lib/WebGUI/Account/Shop.pm b/lib/WebGUI/Account/Shop.pm new file mode 100644 index 000000000..1eb720fbe --- /dev/null +++ b/lib/WebGUI/Account/Shop.pm @@ -0,0 +1,297 @@ +package WebGUI::Account::Shop; + +use strict; + +use WebGUI::Exception; +use WebGUI::International; +use WebGUI::Pluggable; +use WebGUI::Utility; +use base qw/WebGUI::Account/; + +=head1 NAME + +Package WebGUI::Account::Shop + +=head1 DESCRIPTION + +Shop Features built into the Account system + +=head1 SYNOPSIS + +use WebGUI::Account::Shop; + +=head1 METHODS + +These methods are available from this class: + +=cut + +#------------------------------------------------------------------- + +=head2 appendCommonVars ( var ) + + Appends common template variables that shop templates will use + +=head3 var + + The hash reference to append template variables to + +=cut + +sub appendCommonVars { + my $self = shift; + my $var = shift; + + $self->SUPER::appendCommonVars($var); + + my $session = $self->session; + my $user = $session->user; + my $method = $session->form->get("do"); + + $var->{'manage_purchases_url' } = $self->getUrl("module=shop;do=managePurchases"); + $var->{'managesPurchasesIsActive'} = WebGUI::Utility::isIn($method,("","managePurchases","view","viewTransaction")); +} + +#------------------------------------------------------------------- + +=head2 canView ( ) + + Returns whether or not the user can view the the tab for this module + +=cut + +sub canView { + my $self = shift; + return ($self->uid eq ""); +} + +#------------------------------------------------------------------- + +=head2 editSettingsForm ( ) + + Creates form elements for user settings page custom to this account module + +=cut + +sub editSettingsForm { + my $self = shift; + my $session = $self->session; + my $i18n = WebGUI::International->new($session,'Account_Shop'); + my $shopi18n = WebGUI::International->new($session,'Shop'); + my $f = WebGUI::HTMLForm->new($session); + + $f->template( + name => "shopStyleTemplateId", + value => $self->getStyleTemplateId, + namespace => "style", + label => $i18n->get("shop style template label"), + hoverHelp => $i18n->get("shop style template hoverHelp") + ); + $f->template( + name => "shopLayoutTemplateId", + value => $self->getLayoutTemplateId, + namespace => "Account/Layout", + label => $i18n->get("shop layout template label"), + hoverHelp => $i18n->get("shop layout template hoverHelp") + ); + $f->template( + name => "shopMyPurchasesTemplateId", + value => $self->session->setting->get("shopMyPurchasesTemplateId"), + namespace => "Shop/MyPurchases", + label => $shopi18n->get("my purchases template"), + hoverHelp => $shopi18n->get("my purchases template help") + ); + $f->template( + name => "shopMyPurchasesDetailTemplateId", + value => $self->session->setting->get("shopMyPurchasesDetailTemplateId"), + namespace => "Shop/MyPurchasesDetail", + label => $shopi18n->get("my purchases detail template"), + hoverHelp => $shopi18n->get("my purchases detail template help") + ); + + return $f->printRowsOnly; +} + +#------------------------------------------------------------------- + +=head2 editSettingsFormSave ( ) + + Creates form elements for the 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("shopStyleTemplateId", $form->process("shopStyleTemplateId","template")); + $setting->set("shopLayoutTemplateId", $form->process("shopLayoutTemplateId","template")); + $setting->set("shopMyPurchasesTemplateId", $form->process("shopMyPurchasesTemplateId","template")); + $setting->set("shopMyPurchasesDetailTemplateId", $form->process("shopMyPurchasesDetailTemplateId","template")); +} + +#------------------------------------------------------------------- + +=head2 getLayoutTemplateId ( ) + +This method returns the templateId for the layout of your new module. + +=cut + +sub getLayoutTemplateId { + my $self = shift; + return $self->session->setting->get("shopLayoutTemplateId") || "aUDsJ-vB9RgP-AYvPOy8FQ"; +} + + +#------------------------------------------------------------------- + +=head2 getStyleTemplateId ( ) + +This method returns the template ID for the main style. + +=cut + +sub getStyleTemplateId { + my $self = shift; + return $self->session->setting->get("shopStyleTemplateId") || $self->SUPER::getStyleTemplateId; +} + +#------------------------------------------------------------------- + +=head2 www_managePurchases ( ) + +The main view page for editing the user's profile. + +=cut + +sub www_managePurchases { + my $self = shift; + my $session = $self->session; + my $url = $session->url; + + my $var = {}; + + # build list + foreach my $id (@{WebGUI::Shop::Transaction->getTransactionIdsForUser($session)}) { + my $transaction = WebGUI::Shop::Transaction->new($session, $id); + push @{$var->{transactions}}, { + %{$transaction->get}, + viewDetailUrl => $self->getUrl('op=account;module=shop;do=viewTransaction;transactionId='.$id), + amount => sprintf("%.2f", $transaction->get('amount')), + }; + } + + $self->appendCommonVars($var); + + return $self->processTemplate($var,$session->setting->get("shopMyPurchasesTemplateId")); +} + +#------------------------------------------------------------------- + +=head2 www_view ( ) + +The main view page for editing the user's profile. + +=cut + +sub www_view { + my $self = shift; + + #Use the view class as the driver for now. This will likely grow + return $self->www_managePurchases(); + +} + +#------------------------------------------------------------------- + +=head2 www_viewTransaction ( ) + +The main view page for editing the user's profile. + +=cut + +sub www_viewTransaction { + my $self = shift; + my $session = $self->session; + + my $transactionId = $session->form->get('transactionId'); + my $transaction = shift || WebGUI::Shop::Transaction->new($session,$transactionId); + my $notice = shift; + + return $session->insufficient unless ($transaction->get('userId') eq $session->user->userId); + + my $i18n = WebGUI::International->new($session, 'Shop'); + my $i18n = WebGUI::International->new($session, 'Shop'); + my ($style, $url) = $session->quick(qw(style url)); + + my %var = ( + %{$transaction->get}, + notice => $notice, + cancelRecurringUrl => $url->page('shop=transaction;method=cancelRecurring;transactionId='.$transaction->getId), + amount => sprintf("%.2f", $transaction->get('amount')), + inShopCreditDeduction => sprintf("%.2f", $transaction->get('inShopCreditDeduction')), + taxes => sprintf("%.2f", $transaction->get('taxes')), + shippingPrice => sprintf("%.2f", $transaction->get('shippingPrice')), + shippingAddress => $transaction->formatAddress({ + name => $transaction->get('shippingAddressName'), + address1 => $transaction->get('shippingAddress1'), + address2 => $transaction->get('shippingAddress2'), + address3 => $transaction->get('shippingAddress3'), + city => $transaction->get('shippingCity'), + state => $transaction->get('shippingState'), + code => $transaction->get('shippingCode'), + country => $transaction->get('shippingCountry'), + phoneNumber => $transaction->get('shippingPhoneNumber'), + }), + paymentAddress => $transaction->formatAddress({ + name => $transaction->get('paymentAddressName'), + address1 => $transaction->get('paymentAddress1'), + address2 => $transaction->get('paymentAddress2'), + address3 => $transaction->get('paymentAddress3'), + city => $transaction->get('paymentCity'), + state => $transaction->get('paymentState'), + code => $transaction->get('paymentCode'), + country => $transaction->get('paymentCountry'), + phoneNumber => $transaction->get('paymentPhoneNumber'), + }), + ); + + # items + my @items = (); + foreach my $item (@{$transaction->getItems}) { + my $address = ''; + if ($transaction->get('shippingAddressId') ne $item->get('shippingAddressId')) { + $address = $transaction->formatAddress({ + name => $item->get('shippingAddressName'), + address1 => $item->get('shippingAddress1'), + address2 => $item->get('shippingAddress2'), + address3 => $item->get('shippingAddress3'), + city => $item->get('shippingCity'), + state => $item->get('shippingState'), + code => $item->get('shippingCode'), + country => $item->get('shippingCountry'), + phoneNumber => $item->get('shippingPhoneNumber'), + }); + } + push @items, { + %{$item->get}, + viewItemUrl => $url->page('shop=transaction;method=viewItem;transactionId='.$transaction->getId.';itemId='.$item->getId), + price => sprintf("%.2f", $item->get('price')), + itemShippingAddress => $address, + orderStatus => $i18n->get($item->get('orderStatus')), + }; + } + $var{items} = \@items; + + $self->appendCommonVars(\%var); + + # render + return $self->processTemplate(\%var,$session->setting->get("shopMyPurchasesDetailTemplateId")); +} + + + +1; diff --git a/lib/WebGUI/Account/User.pm b/lib/WebGUI/Account/User.pm new file mode 100644 index 000000000..37185c1bf --- /dev/null +++ b/lib/WebGUI/Account/User.pm @@ -0,0 +1,145 @@ +package WebGUI::Account::User; + +use strict; + +use WebGUI::Exception; +use WebGUI::International; +use WebGUI::Pluggable; +use WebGUI::Utility; +use WebGUI::Operation::Auth; + +use base qw/WebGUI::Account/; + +=head1 NAME + +Package WebGUI::Account::User + +=head1 DESCRIPTION + +This is the class which is used to display a users's account details + +=head1 SYNOPSIS + + use WebGUI::Account::User; + +=head1 METHODS + +These subroutines are available from this package: + +=cut + +#------------------------------------------------------------------- + +=head2 canView ( ) + + Returns whether or not the user can view the inbox tab + +=cut + +sub canView { + my $self = shift; + return ($self->uid eq ""); +} + +#------------------------------------------------------------------- + +=head2 editSettingsForm ( ) + + Creates form elements for user settings page custom to this account module + +=cut + +sub editSettingsForm { + my $self = shift; + my $session = $self->session; + my $setting = $session->setting; + my $i18n = WebGUI::International->new($session,'Account_User'); + my $f = WebGUI::HTMLForm->new($session); + + $f->template( + name => "userAccountStyleTemplateId", + value => $self->session->setting->get("userAccountStyleTemplateId"), + namespace => "style", + label => $i18n->get("user style template label"), + hoverHelp => $i18n->get("user style template hoverHelp") + ); + $f->template( + name => "userAccountLayoutTemplateId", + value => $self->session->setting->get("userAccountLayoutTemplateId"), + namespace => "Account/Layout", + label => $i18n->get("layout template label"), + hoverHelp => $i18n->get("layout template hoverHelp") + ); + $f->raw(q{ }); + $f->readOnly ( + value => $i18n->get("templates in auth method message"), + ); + + return $f->printRowsOnly; +} + +#------------------------------------------------------------------- + +=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("userAccountStyleTemplateId", $form->process("userAccountStyleTemplateId","template")); + $setting->set("userAccountLayoutTemplateId", $form->process("userAccountLayoutTemplateId","template")); +} + +#------------------------------------------------------------------- + +=head2 getLayoutTemplateId ( ) + +This method returns the template ID for the account layout. + +=cut + +sub getLayoutTemplateId { + my $self = shift; + return $self->session->setting->get("userAccountLayoutTemplateId") || "9ThW278DWLV0-Svf68ljFQ"; +} + + +#------------------------------------------------------------------- + +=head2 getStyleTemplateId ( ) + +This method returns the template ID for the main style. + +=cut + +sub getStyleTemplateId { + my $self = shift; + return $self->session->setting->get("userAccountStyleTemplateId") || $self->SUPER::getStyleTemplateId; +} + + +#------------------------------------------------------------------- + +=head2 www_view ( ) + +The main view page for editing the user's profile. + +=cut + +sub www_view { + my $self = shift; + my $session = $self->session; + + my $auth = WebGUI::Operation::Auth::getInstance($session); + + return $auth->displayAccount; +} + + +1; diff --git a/lib/WebGUI/Account/_NewModule.skeleton b/lib/WebGUI/Account/_NewModule.skeleton new file mode 100644 index 000000000..7c665f462 --- /dev/null +++ b/lib/WebGUI/Account/_NewModule.skeleton @@ -0,0 +1,145 @@ +package WebGUI::Account::NewModule; + +use strict; + +use WebGUI::Exception; +use WebGUI::International; +use WebGUI::Pluggable; +use WebGUI::Utility; +use base qw/WebGUI::Account/; + +=head1 NAME + +Package WebGUI::Account::NewAsset + +=head1 DESCRIPTION + +Describe your New Account Module's functionality and features here. + +=head1 SYNOPSIS + +use WebGUI::Account::NewModule; + + +=head1 METHODS + +These methods are available from this class: + +=cut + +#------------------------------------------------------------------- + +=head2 canView ( ) + + Returns whether or not the user can view the the tab for this module + +=cut + +sub canView { + my $self = shift; + return 1; +} + +#------------------------------------------------------------------- + +=head2 editSettingsForm ( ) + + Creates form elements for user settings page custom to this account module + +=cut + +sub editSettingsForm { + my $self = shift; + my $session = $self->session; + my $i18n = WebGUI::International->new($session,'Account_NewModule'); + my $f = WebGUI::HTMLForm->new($session); + + $f->template( + name => "moduleStyleTemplateId", + value => $self->getStyleTemplateId, + namespace => "style", + label => $i18n->get("style template label"), + hoverHelp => $i18n->get("style template hoverHelp") + ); + $f->template( + name => "moduleLayoutTemplateId", + value => $self->getLayoutTemplateId, + namespace => "Account/Layout", + label => $i18n->get("layout template label"), + hoverHelp => $i18n->get("layout template hoverHelp") + ); + $f->template( + name => "moduleViewTemplateId", + value => $self->session->setting->get("moduleViewTemplateId"), + namespace => "Account/NewModule/View", + label => $i18n->get("view template label"), + hoverHelp => $i18n->get("view template hoverHelp") + ); + + return $f->printRowsOnly; +} + +#------------------------------------------------------------------- + +=head2 editSettingsFormSave ( ) + + Creates form elements for the 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("moduleStyleTemplateId", $form->process("moduleStyleTemplateId","template")); + $setting->set("moduleLayoutTemplateId", $form->process("moduleLayoutTemplateId","template")); + $setting->set("moduleViewTemplateId", $form->process("moduleViewTemplateId","template")); +} + +#------------------------------------------------------------------- + +=head2 getLayoutTemplateId ( ) + +This method returns the templateId for the layout of your new module. + +=cut + +sub getLayoutTemplateId { + my $self = shift; + return $self->session->setting->get("moduleLayoutTempalteId") || $self->SUPER::getLayoutTemplateId; +} + + +#------------------------------------------------------------------- + +=head2 getStyleTemplateId ( ) + +This method returns the template ID for the main style. + +=cut + +sub getStyleTemplateId { + my $self = shift; + return $self->session->setting->get("moduleStyleTemplateId") || $self->SUPER::getStyleTemplateId; +} + +#------------------------------------------------------------------- + +=head2 www_view ( ) + +The main view page for editing the user's profile. + +=cut + +sub www_view { + my $self = shift; + my $session = $self->session; + my $var = {}; + + return $self->processTemplate($var,$session->setting->get("moduleViewTemplateId")); +} + + +1; diff --git a/lib/WebGUI/Asset/Post.pm b/lib/WebGUI/Asset/Post.pm index 3efa89461..bec58b3ad 100644 --- a/lib/WebGUI/Asset/Post.pm +++ b/lib/WebGUI/Asset/Post.pm @@ -418,7 +418,7 @@ Formats the url to view a users profile. sub getPosterProfileUrl { my $self = shift; - return $self->getUrl("op=viewProfile;uid=".$self->get("ownerUserId")); + return WebGUI::User->new($self->session,$self->get("ownerUserId"))->getProfileUrl; } #------------------------------------------------------------------- diff --git a/lib/WebGUI/Asset/Shortcut.pm b/lib/WebGUI/Asset/Shortcut.pm index 0497f6151..ec21a452d 100644 --- a/lib/WebGUI/Asset/Shortcut.pm +++ b/lib/WebGUI/Asset/Shortcut.pm @@ -847,7 +847,7 @@ sub www_saveUserPrefs { my $field = WebGUI::ProfileField->new($self->session,$fieldId); next unless $field; $data{$field->getId} = $field->formProcess; - if ($field->getId eq 'email' && WebGUI::Operation::Profile::isDuplicateEmail($self->session,$data{$field->getId})) { + if ($field->getId eq 'email' && $field->isDuplicate($data{$field->getId})) { return '

  • '.$i18n->get(1072).'
  • '; } if ($field->isRequired && !$data{$field->getId}) { diff --git a/lib/WebGUI/Auth.pm b/lib/WebGUI/Auth.pm index b23cca58b..486f49ac1 100755 --- a/lib/WebGUI/Auth.pm +++ b/lib/WebGUI/Auth.pm @@ -270,7 +270,7 @@ Password entered by the user. This is only used in for sending the user a notif =head3 profile -Hashref of profile values returned by the function WebGUI::Operation::Profile::validateProfileData($self->session) +Hashref of profile values returned by the function WebGUI::User::validateProfileDataFromForm($fields); =cut @@ -290,8 +290,8 @@ sub createAccountSave { $u->username($username); $u->authMethod($self->authMethod); $u->karma($self->session->setting->get("karmaPerLogin"),"Login","Just for logging in.") if ($self->session->setting->get("useKarma")); - WebGUI::Operation::Profile::saveProfileFields($self->session,$u,$profile) if($profile); - $self->saveParams($userId,$self->authMethod,$properties); + $u->updateProfileFields($profile) if ($profile); + $self->saveParams($userId,$self->authMethod,$properties); if ($self->getSetting("sendWelcomeMessage")){ my $authInfo = "\n\n".$i18n->get(50).": ".$username; @@ -460,10 +460,10 @@ Array ref of template vars from subclass =cut sub displayAccount { - my $self = shift; - my $method = $_[0]; - my $vars = $_[1]; - + my $self = shift; + my $method = shift; + my $vars = shift; + my $i18n = WebGUI::International->new($self->session); $vars->{title} = $i18n->get(61); @@ -477,8 +477,21 @@ sub displayAccount { $vars->{'account.form.submit'} = WebGUI::Form::submit($self->session,{}); $vars->{'account.form.footer'} = WebGUI::Form::formFooter($self->session,); - $vars->{'account.options'} = WebGUI::Operation::Shared::accountOptions($self->session); - return WebGUI::Asset::Template->new($self->session,$self->getAccountTemplateId)->process($vars); + #Appends 'account.options' loop along with some new links + WebGUI::Account->appendAccountLinks($self->session,$vars); + + ########### ACCOUNT SHUNT + #The following is a shunt which allows the displayAccount page to be displayed in the + #Account system. This shunt will be replaced in WebGUI 8 when the API can be broken + my $output = WebGUI::Asset::Template->new($self->session,$self->getAccountTemplateId)->process($vars); + #If the account system is calling this method, just return the template + my $op = $self->session->form->get("op"); + if($op eq "account") { + return $output; + } + #Otherwise wrap the template into the account layout + my $instance = WebGUI::Content::Account->createInstance($self->session,"user"); + return $instance->displayContent($output,1); } #------------------------------------------------------------------- diff --git a/lib/WebGUI/Auth/LDAP.pm b/lib/WebGUI/Auth/LDAP.pm index bbf23d7d2..c025c0b4c 100644 --- a/lib/WebGUI/Auth/LDAP.pm +++ b/lib/WebGUI/Auth/LDAP.pm @@ -304,9 +304,18 @@ sub createAccountSave { #Check that username is valid and not a duplicate in the system. $error .= $self->error if(!$self->validUsername($username)); #Validate profile data. - my ($profile, $temp, $warning) = WebGUI::Operation::Profile::validateProfileData($self->session); + my $fields = WebGUI::ProfileField->getEditableFields($self->session); + my $retHash = $self->user->validateProfileDataFromForm($fields); + my $profile = $retHash->{profile}; + my $temp = ""; + my $warning = ""; + + my $format = "
  • %s
  • "; + map { $warning .= sprintf($format,$_) } @{$retHash->{warnings}}; + map { $temp .= sprintf($format,$_) } @{$retHash->{errors}}; + $error .= $temp; - return $self->createAccount("
  • ".$error."") unless ($error eq ""); + return $self->createAccount("
  • ".$error."
  • ") unless ($error eq ""); #If Email address is not unique, a warning is displayed if($warning ne "" && !$self->session->form->process("confirm")){ return $self->createAccount('
  • '.$i18n->get(1078).'
  • ', 1); @@ -336,18 +345,30 @@ sub deactivateAccountConfirm { #------------------------------------------------------------------- sub displayAccount { - my $self = shift; - my $vars; - return $self->displayLogin($_[0]) if ($self->isVisitor); + my $self = shift; + my $vars; + return $self->displayLogin($_[0]) if ($self->isVisitor); my $i18n = WebGUI::International->new($self->session); - $vars->{displayTitle} = '

    '.$i18n->get(61).'

    '; - $vars->{'account.message'} = $i18n->get(856); - if($self->session->setting->get("useKarma")){ - $vars->{'account.form.karma'} = $self->session->user->profileField("karma"); - $vars->{'account.form.karma.label'} = $i18n->get(537); - } - $vars->{'account.options'} = WebGUI::Operation::Shared::accountOptions($self->session); - return WebGUI::Asset::Template->new($self->session,$self->getAccountTemplateId)->process($vars); + $vars->{displayTitle} = '

    '.$i18n->get(61).'

    '; + $vars->{'account.message'} = $i18n->get(856); + if($self->session->setting->get("useKarma")){ + $vars->{'account.form.karma'} = $self->session->user->profileField("karma"); + $vars->{'account.form.karma.label'} = $i18n->get(537); + } + WebGUI::Account->appendAccountLinks($self->session,$vars); + + ########### ACCOUNT SHUNT + #The following is a shunt which allows the displayAccount page to be displayed in the + #Account system. This shunt will be replaced in WebGUI 8 when the API can be broken + my $output = WebGUI::Asset::Template->new($self->session,$self->getAccountTemplateId)->process($vars); + #If the account system is calling this method, just return the template + my $op = $self->session->form->get("op"); + if($op eq "account") { + return $output; + } + #Otherwise wrap the template into the account layout + my $instance = WebGUI::Content::Account->createInstance($self->session,"user"); + return $instance->displayContent($output,1); } #------------------------------------------------------------------- @@ -580,5 +601,4 @@ sub setConnectDN { } -1; - +1; \ No newline at end of file diff --git a/lib/WebGUI/Auth/WebGUI.pm b/lib/WebGUI/Auth/WebGUI.pm index f93aa1b0b..087d31d4b 100644 --- a/lib/WebGUI/Auth/WebGUI.pm +++ b/lib/WebGUI/Auth/WebGUI.pm @@ -229,7 +229,17 @@ sub createAccountSave { } } $error .= $self->error unless($self->_isValidPassword($password,$passConfirm)); - my ($profile, $temp, $warning) = WebGUI::Operation::Profile::validateProfileData($self->session, {regOnly => 1}); + + my $fields = WebGUI::ProfileField->getRegistrationFields($session); + my $retHash = $self->user->validateProfileDataFromForm($fields); + my $profile = $retHash->{profile}; + my $temp = ""; + my $warning = ""; + + my $format = "
  • %s
  • "; + map { $warning .= sprintf($format,$_) } @{$retHash->{warnings}}; + map { $temp .= sprintf($format,$_) } @{$retHash->{errors}}; + $error .= $temp; unless ($error eq "") { diff --git a/lib/WebGUI/Content/Account.pm b/lib/WebGUI/Content/Account.pm new file mode 100644 index 000000000..6978381e0 --- /dev/null +++ b/lib/WebGUI/Content/Account.pm @@ -0,0 +1,180 @@ +package WebGUI::Content::Account; + +=head1 LEGAL + + ------------------------------------------------------------------- + WebGUI is Copyright 2001-2008 Plain Black Corporation. + ------------------------------------------------------------------- + Please read the legal notices (docs/legal.txt) and the license + (docs/license.txt) that came with this distribution before using + this software. + ------------------------------------------------------------------- + http://www.plainblack.com info@plainblack.com + ------------------------------------------------------------------- + +=cut + +use strict; +use WebGUI::Session; +use WebGUI::Exception; +use Carp qw(croak); + +=head1 NAME + +Package WebGUI::Content::Account + +=head1 DESCRIPTION + +A content handler that opens up all the account functionality. Account modules are accessed via the url like this: + + /pagename?op=module;do=www_method + +For example: + + /home?op=profile;do=edit + +In the above we're accessing the www_edit method in the WebGUI::Account::Profile module. + +Module op relationships are stored in the config file as such + +account : { + "profile" : "WebGUI::Account::Profile", + "inbox" : "WebGUI::Account::Inbox", + "network" : "WebGUI::Account::Network", + "user" : "WebGUI::Account::User", + "custom" : "WebGUI::Account::Custom" +} + +=head1 SYNOPSIS + + use WebGUI::Content::Account; + my $output = WebGUI::Content::Account::handler($session); + +=head1 SUBROUTINES + +These subroutines are available from this package: + +=cut + + +#------------------------------------------------------------------- + +=head2 createInstance ( session, module ) + +Creates an instance of an account pluggin + +=session + +WebGUI::Session object + +=module + +Module the method is in. Defaults to the profileModuleIdentifier in the config file + +=cut + +sub createInstance { + my $class = shift; + my $session = shift; + my $module = shift || $session->config->get("profileModuleIdentifier"); + + #Get the account config to work with + my $configs = $session->config->get("account"); + my $config = __PACKAGE__->getAccountConfig($session,$module,$configs); + + #Throw an error if the config file isn't found + unless (defined $config) { + WebGUI::Error->throw( error => qq{Could not locate module $module in the account system}); + return undef; + } + + #Visitor cannot access the acccount system + return $session->privilege->insufficient if($session->user->isVisitor); + + #Create Pluggin Object + #Don't eval this as pluggable will croak and we want the calling module to handle the exception + my $pluggin = WebGUI::Pluggable::instanciate( + $config->{className}, + "new", + [ $session, $module ] + ); + + #Check to make sure pluggin is a subclass of WebGUI::Account + unless($pluggin->isa('WebGUI::Account')) { + my $plugginType = ref $pluggin; + WebGUI::Error::InvalidObject->throw( + expected => 'WebGUI::Account', + got => $plugginType, + error => '$plugginType is not a subclass of WebGUI::Accout' + ); + return undef; + } + + return $pluggin; +} + + + +#------------------------------------------------------------------- + +=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. + +=cut + +sub handler { + my $session = shift; + my $form = $session->form; + my $setting = $session->setting; + + #Pass through if it's not the account op + return undef unless ($form->get("op") eq "account"); + + my $module = $form->get("module"); + my $method = $form->get("do"); + my $uid = $form->get("uid"); + + my $instance = __PACKAGE__->createInstance($session,$module); + + #Let the content handler handle trapping errors + my $output = $instance->callMethod($method,[],$uid); + return undef unless (defined $output); + + return $instance->displayContent($output); + +} + + +1; + diff --git a/lib/WebGUI/Friends.pm b/lib/WebGUI/Friends.pm index 2b7d98242..c28a1cdae 100644 --- a/lib/WebGUI/Friends.pm +++ b/lib/WebGUI/Friends.pm @@ -149,6 +149,61 @@ sub getAllPendingAddRequests { } +#------------------------------------------------------------------- + +=head2 getNextInvitation ( invitation ) + +Returns the invitation that was sent to the user just after the invitation passed in. + +=cut + +sub getNextInvitation { + my $self = shift; + my $invitation = shift; + + my $sql = q{ + select + * + from + friendInvitations + where + friendId = ? + and dateSent > ? + order by dateSent asc + limit 1 + }; + my $bindvars = [$self->user->userId,$invitation->{dateSent}]; + return $self->session->db->quickHashRef($sql,$bindvars); +} + + +#------------------------------------------------------------------- + +=head2 getPreviousInvitation ( invitation ) + +Returns the invitation that was sent to the user just before the invitation passed in. + +=cut + +sub getPreviousInvitation { + my $self = shift; + my $invitation = shift; + + my $sql = q{ + select + * + from + friendInvitations + where + friendId = ? + and dateSent < ? + order by dateSent desc + limit 1 + }; + my $bindvars = [$self->user->userId,$invitation->{dateSent}]; + return $self->session->db->quickHashRef($sql,$bindvars); +} + #------------------------------------------------------------------- =head2 isFriend ( userId ) @@ -193,7 +248,7 @@ sub isInvited { inviterId = ? and friendId = ? }, - [$session->user->userId,$userId]); + [$self->user->userId,$userId]); return $isInvited; } @@ -268,12 +323,19 @@ The user to invite to be a friend. The message to lure them to accept. +=head inviteUrl + +The url to view the friend request + =cut sub sendAddRequest { - my $self = shift; - my $userId = shift; - my $comments = shift; + my $self = shift; + my $userId = shift; + my $comments = shift; + my $url = $self->session->url; + my $inviteUrl = shift || $url->append($url->getSiteURL,'op=account'); + my $i18n = WebGUI::International->new($self->session, "Friends"); # No sneaky attack paths... @@ -281,7 +343,9 @@ sub sendAddRequest { # Create the invitation url. my $inviteId = $self->session->id->generate(); - my $inviteUrl = $self->session->url->append($self->session->url->getSiteURL, 'op=friendRequest;inviteId='.$inviteId); + + $inviteUrl = $url->append($inviteUrl,'inviteId='.$inviteId); + # Build the message my $messageText = sprintf $i18n->get("invitation approval email"), $self->user->getWholeName, $self->session->url->getSiteURL, $comments, $inviteUrl; @@ -346,4 +410,4 @@ sub sendMessage { } } -1; +1; \ No newline at end of file diff --git a/lib/WebGUI/Group.pm b/lib/WebGUI/Group.pm index fe7fca17d..fbc0b4318 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]); +} #------------------------------------------------------------------- @@ -1050,10 +1074,9 @@ sub name { return $self->get("groupName"); } - #------------------------------------------------------------------- -=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", { noclone => 1}); 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(); @@ -1106,6 +1134,7 @@ sub new { return $self; } + #------------------------------------------------------------------- =head2 scratchFilter ( [ value ] ) diff --git a/lib/WebGUI/Inbox.pm b/lib/WebGUI/Inbox.pm index 852534dc1..2c3e01c2e 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 message that was send after the message passed in 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 => "asc", + limit => 1 + }); + + my $message = $self->session->db->quickHashRef($sql); + + return $self->getMessage($message->{messageId}); +} + +#------------------------------------------------------------------- + +=head2 getPreviousMessage ( message [, userId] ) + +Returns the message that was sent before the message passed in 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 => "desc", + 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] + ); +} + + #------------------------------------------------------------------- @@ -221,5 +539,4 @@ sub session { } -1; - +1; \ No newline at end of file diff --git a/lib/WebGUI/Inbox/Message.pm b/lib/WebGUI/Inbox/Message.pm index 8b0438744..8dbd86edc 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; } #------------------------------------------------------------------- @@ -258,12 +378,84 @@ The id of the user that completed this task. Defaults to the current user. sub setCompleted { my $self = shift; my $userId = shift || $self->session->user->userId; - $self->{_properties}{status} = "completed"; + $self->{_properties}{status} = "completed"; $self->{_properties}{completedBy} = $userId; $self->{_properties}{completedOn} = time(); - $self->session->db->setRow("inbox","messageId",$self->{_properties}); + $self->{_inbox}{status} = "completed"; + $self->{_inbox}{completedBy} = $userId; + $self->{_inbox}{completedOn} = time(); + $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 +473,113 @@ 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); + } + + #Only let completed stuff go back to pending + if ( $status eq "pending" && $self->{_properties}{status} eq "completed") { + $self->{_properties}{status} = "pending"; + $self->{_inbox}{status} = "pending" + } + + $self->session->db->setRow("inbox","messageId",$self->{_inbox}); return undef; } -1; +#------------------------------------------------------------------- +=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; \ No newline at end of file diff --git a/lib/WebGUI/Macro/FileUrl.pm b/lib/WebGUI/Macro/FileUrl.pm index d3db012e0..5c412db7c 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,54 @@ 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. + +head3 isImage + +If id is passed in and the isImage flag is set, the first image will be 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 $isImage = shift; + my $i18n = WebGUI::International->new($session, 'Macro_FileUrl'); + + #Handle storageId case + if($isStorageId && $id) { + my $store = undef; + if($isImage) { + $store = WebGUI::Storage::Image->get($session,$id); + } + else { + $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/Macro/NewMail.pm b/lib/WebGUI/Macro/NewMail.pm index 2debd1531..1ba2b6a61 100644 --- a/lib/WebGUI/Macro/NewMail.pm +++ b/lib/WebGUI/Macro/NewMail.pm @@ -29,7 +29,7 @@ sub _createURL { my $session = shift; my $text = shift; my $class = shift; - my $url = '
    url->page("op=account;module=inbox").'"'; $url .= ' class="'.$class.'"' if($class); $url .= '>'.$text.''; return $url; diff --git a/lib/WebGUI/Macro/User.pm b/lib/WebGUI/Macro/User.pm index af451c7d1..7d1293bf8 100644 --- a/lib/WebGUI/Macro/User.pm +++ b/lib/WebGUI/Macro/User.pm @@ -18,22 +18,39 @@ Package WebGUI::Macro::User =head1 DESCRIPTION -Macro for displaying information from the current User's profile. +Macro for displaying information from the a User's profile. -=head2 process( field ) +=head2 process( field [, userId] ) -process takes a single parameter, the name of a field in the current user's User Profile from -the data stored in $session . If the field does not exist, undef is returned. +This macro tries to return the profile field passed in for the user +passed in. If not user is passed in, the current user in session +will be used. + +=head3 field + +field to return + +=head3 userId + +optional userId of the user to return the field for. If this field is +empty, the profile field for the default user will be returned =cut #------------------------------------------------------------------- sub process { - my $session = shift; - return $session->user->profileField(shift); + my $session = shift; + my $field = shift; + my $userId = shift; + + return undef unless ($field); + + my $user = ($userId) + ? WebGUI::User->new($session,$userId) + : $session->user + ; + + return $user->profileField($field); } - -1; - - +1; \ No newline at end of file diff --git a/lib/WebGUI/Operation.pm b/lib/WebGUI/Operation.pm index 12ab28ab5..10e528fc6 100644 --- a/lib/WebGUI/Operation.pm +++ b/lib/WebGUI/Operation.pm @@ -135,20 +135,14 @@ sub getOperations { 'viewInbox' => 'Inbox', 'viewInboxMessage' => 'Inbox', 'sendPrivateMessage' => 'Inbox', - 'sendPrivateMessageSave' => 'Inbox', - 'deletePrivateMessage' => 'Inbox', 'inviteUser' => 'Invite', 'inviteUserSave' => 'Invite', 'acceptInvite' => 'Invite', 'addFriend' => 'Friends', - 'addFriendSave' => 'Friends', 'friendRequest' => 'Friends', - 'friendRequestSave' => 'Friends', 'manageFriends' => 'Friends', - 'removeFriends' => 'Friends', - 'sendMessageToFriends' => 'Friends', 'copyLDAPLink' => 'LDAPLink', 'deleteLDAPLink' => 'LDAPLink', @@ -159,7 +153,6 @@ sub getOperations { 'viewLoginHistory' => 'LoginHistory', 'editProfile' => 'Profile', - 'editProfileSave' => 'Profile', 'viewProfile' => 'Profile', 'deleteProfileCategory' => 'ProfileSettings', diff --git a/lib/WebGUI/Operation/Friends.pm b/lib/WebGUI/Operation/Friends.pm index 84b53a5eb..f7da81311 100644 --- a/lib/WebGUI/Operation/Friends.pm +++ b/lib/WebGUI/Operation/Friends.pm @@ -11,11 +11,7 @@ package WebGUI::Operation::Friends; #------------------------------------------------------------------- use strict; -use WebGUI::Form; -use WebGUI::Friends; -use WebGUI::User; -use WebGUI::International; -use WebGUI::Operation::Shared; +use WebGUI::Content::Account; =head1 NAME @@ -25,372 +21,53 @@ Package WebGUI::Operation::Friends Operation handler for handling the friends network. +DEPRECATED - Do not use this package in new code. + =cut #------------------------------------------------------------------- =head2 www_addFriend ( ) -Form for inviting a user to become your friend. +DEPRECATED - See WebGUI::Account::Friends::sendFriendsRequest =cut sub www_addFriend { my $session = shift; - return $session->privilege->insufficient() unless ($session->user->isRegistered); - my $friendId = $session->form->get('userId'); - my $protoFriend = WebGUI::User->new($session, $friendId); - - my $i18n = WebGUI::International->new($session, 'Friends'); - - my $friends = WebGUI::Friends->new($session); - if($friends->isFriend($friendId)) { - my $returnToProfile = sprintf($i18n->get('add to friends profile'),$protoFriend->getFirstName); - my $backUrl = $session->url->append($session->url->getRequestedUrl, 'op=viewProfile;uid='.$friendId); - return $session->style->userStyle( - sprintf($i18n->get("error user is already friend"),$backUrl,$returnToProfile) - ); - } - elsif($friends->isInvited($friendId)) { - my $returnToProfile = sprintf($i18n->get('add to friends profile'),$protoFriend->getFirstName); - my $backUrl = $session->url->append($session->url->getRequestedUrl, 'op=viewProfile;uid='.$friendId); - return $session->style->userStyle( - sprintf($i18n->get("error user is already invited"),$backUrl,$returnToProfile) - ); - } - - # Check for non-existant user id. - if ((!$protoFriend->username) || (!$protoFriend->profileField('ableToBeFriend'))) { - my $output = sprintf qq!

    %s

    \n

    %s

    %s!, - $i18n->get('add to friends'), - $i18n->get('does not want to be a friend'), - $session->url->getBackToSiteURL(), - $i18n->get('493', 'WebGUI'); - return $session->style->userStyle($output); - } - - my $output = join '', - sprintf("

    %s

    \n", $i18n->get('add to friends')), - '

    ', - sprintf($i18n->get('add to friends description'), - $protoFriend->getWholeName), - '

    ', - WebGUI::Form::formHeader($session), - WebGUI::Form::hidden($session, - { - name => 'op', - value => 'addFriendSave', - } - ), - WebGUI::Form::hidden($session, - { - name => 'userId', - value => $friendId, - } - ), - WebGUI::Form::textarea($session, - { - name => 'comments', - value => sprintf($i18n->get('default friend comments'), $protoFriend->getFirstName, $session->user->getFirstName), - } - ), - WebGUI::Form::Submit($session, - { - value => $i18n->get('add') - } - ), - WebGUI::Form::Button($session, - { - value => $i18n->get('cancel', 'WebGUI'), - extras => q|onclick="history.go(-1);" class="backwardButton"|, - } - ), - WebGUI::Form::formFooter($session), - ; - return $session->style->userStyle($output); + my $uid = $session->form->process("userId"); + my $instance = WebGUI::Content::Account->createInstance($session,"friends"); + return $instance->displayContent($instance->callMethod("sendFriendsRequest",[],$uid)); } -#------------------------------------------------------------------- - -=head2 www_addFriendSave ( ) - -Post process the form, check for required fields, handle inviting users who are already -members (determined by email address) and send the email. - -=cut - -sub www_addFriendSave { - my $session = shift; - return $session->privilege->insufficient() unless ($session->user->isRegistered); - - my $friendId = $session->form->get('userId'); - my $protoFriend = WebGUI::User->new($session, $friendId); - my $i18n = WebGUI::International->new($session, 'Friends'); - - my $friends = WebGUI::Friends->new($session); - if($friends->isFriend($friendId) || $friends->isInvited($friendId)) { - return www_addFriend($session); - } - - # Check for non-existant user id. - if ((!$protoFriend->username) || (!$protoFriend->profileField('ableToBeFriend'))) { - my $output = sprintf qq!

    %s

    \n

    %s

    %s!, - $i18n->get('add to friends'), - $i18n->get('does not want to be a friend'), - $session->url->getBackToSiteURL(), - $i18n->get('493', 'WebGUI'); - return $session->style->userStyle($output); - } - - $friends->sendAddRequest($friendId, $session->form->get('comments')); - - # display result - my $output = sprintf( - q!

    %s

    %s

    %s

    %s

    !, - $i18n->get('add to friends'), - sprintf($i18n->get('add to friends confirmation'), $protoFriend->getWholeName), - $session->url->append($session->url->getRequestedUrl, 'op=viewProfile;uid='.$friendId), - sprintf($i18n->get('add to friends profile'), $protoFriend->getFirstName), - $session->url->getBackToSiteURL(), - $i18n->get('493', 'WebGUI'), - ); - return $session->style->userStyle($output); -} #------------------------------------------------------------------- =head2 www_friendRequest ( ) -Form for the friend to accept or deny the request. +DEPRECATED - See WebGUI::Account::Inbox::viewInvitation =cut sub www_friendRequest { my $session = shift; - return $session->privilege->insufficient() unless ($session->user->isRegistered); - - my $i18n = WebGUI::International->new($session, 'Friends'); - - my $inviteId = $session->form->get('inviteId'); - my $friends = WebGUI::Friends->new($session); - - my $invitation = $friends->getAddRequest($inviteId); - - ##Invalid invite ID - unless (exists $invitation->{friendId}) { ##No userId corresponds to the inviteId - my $output = sprintf qq!

    %s

    \n

    %s

    %s!, - $i18n->get('invalid invite code'), - $i18n->get('invalid invite code message'), - $session->url->page("op=viewInbox"), - $i18n->get('354', 'WebGUI'); - return $session->style->userStyle($output); - } - - ##Already a friend (check friendId already in the group) - if ($friends->isFriend($invitation->{inviterId})) { - my $output = sprintf qq!

    %s

    \n

    %s

    %s!, - $i18n->get('invalid invite code'), - $i18n->get('already a friend'), - $session->url->page("op=viewInbox"), - $i18n->get('354', 'WebGUI'); - return $session->style->userStyle($output); - } - - ##Someone else's invite (check friendId vs current userId). - if ($session->user->userId ne $invitation->{friendId}) { ##This isn't your invitation, dude. - my $output = sprintf qq!

    %s

    \n

    %s

    %s!, - $i18n->get('invalid invite code'), - $i18n->get('not the right user'), - $session->url->page("op=viewInbox"), - $i18n->get('354', 'WebGUI'); - return $session->style->userStyle($output); - } - - ##Everything looks good. Make the form! - my $inviter = WebGUI::User->new($session, $invitation->{inviterId}); - my $output = join '', - sprintf("

    %s

    \n", $i18n->get('friend request')), - '

    ', - sprintf($i18n->get('friend request description'), - $inviter->getWholeName), - '

    ', - WebGUI::Form::formHeader($session), - WebGUI::Form::hidden($session, - { - name => 'op', - value => 'friendRequestSave', - } - ), - WebGUI::Form::hidden($session, - { - name => 'inviteId', - value => $inviteId, - } - ), - WebGUI::Form::textarea($session, - { - name => 'comments', - value => $invitation->{comments}, - extras => 'disabled=disabled', - } - ), - WebGUI::Form::Submit($session, ##Approve - { - name => 'doWhat', - value => $i18n->get('572', 'WebGUI'), - } - ), - WebGUI::Form::Submit($session, ##Deny - { - name => 'doWhat', - value => $i18n->get('574', 'WebGUI'), - } - ), - WebGUI::Form::formFooter($session), - ; - return $session->style->userStyle($output); -} - -#------------------------------------------------------------------- - -=head2 www_friendRequestSave ( ) - -Handle form data from the friend's response to the invitation - -=cut - -sub www_friendRequestSave { - my $session = shift; - return $session->privilege->insufficient() unless ($session->user->isRegistered); - - my $i18n = WebGUI::International->new($session, 'Friends'); - my $doWhat = $session->form->get('doWhat'); - my $inviteId = $session->form->get('inviteId'); - my $friends = WebGUI::Friends->new($session); - my $invite = $friends->getAddRequest($inviteId); - my $inviter = WebGUI::User->new($session, $invite->{inviterId}); - ##Invalid invite ID - if (!$invite->{inviterId}) { ##No userId corresponds to the inviteId - my $output = sprintf qq!

    %s

    \n

    %s

    %s!, - $i18n->get('invalid invite code'), - $i18n->get('invalid invite code message'), - $session->url->page("op=viewInbox"), - $i18n->get('354', 'WebGUI'); - return $session->style->userStyle($output); - } - - ##If deny, change the status of the request to denied. - if ($doWhat ne $i18n->get('572', 'WebGUI')) { ##request denied - $friends->rejectAddRequest($inviteId); - ##Return screen that says they denied the request. - my $output = sprintf qq!

    %s

    \n

    %s

    %s!, - $i18n->get('friend request'), - sprintf($i18n->get('you have not been added'), $inviter->getWholeName), - $session->url->page("op=viewInbox"), - $i18n->get('354', 'WebGUI'); - return $session->style->userStyle($output); - } - - ##If accepted, - # set the status to accepted. - $friends->approveAddRequest($inviteId); - - # Return screen that says they accepted the request. - my $output = sprintf qq!

    %s

    \n

    %s

    %s!, - $i18n->get('friend request'), - sprintf($i18n->get('you have been added'), $inviter->getWholeName), - $session->url->page("op=viewInbox"), - $i18n->get('354', 'WebGUI'); - return $session->style->userStyle($output); + my $instance = WebGUI::Content::Account->createInstance($session,"inbox"); + return $instance->displayContent($instance->callMethod("viewInvitation")); } #------------------------------------------------------------------- =head2 www_manageFriends ( ) -Display the list of friends and allow the user to remove friends or -send private messages to a subset of them. + +DEPRECATED - See WebGUI::Account::Friends::view =cut sub www_manageFriends { my $session = shift; - my ($user, $url, $style) = $session->quick(qw(user url style)); - return $session->privilege->insufficient() unless ($user->isRegistered); - my $i18n = WebGUI::International->new($session, 'Friends'); - - ##You have no friends! - my $friends = $user->friends->getUsers; - unless (scalar(@{$friends})) { - my $output = sprintf qq!

    %s

    \n

    %s

    %s!, - $i18n->get('my friends'), - $i18n->get('no friends'), - $url->getBackToSiteURL(), - $i18n->get('493', 'WebGUI'); - return $style->userStyle($output); - } - - # show the friend manager - my %var = ( - "account.options" => WebGUI::Operation::Shared::accountOptions($session), - formHeader => WebGUI::Form::formHeader($session) - . WebGUI::Form::hidden($session, { name => 'op', value => 'sendMessageToFriends', }), - removeFriendButton => WebGUI::Form::button($session, { value => $i18n->get('remove'), extras => q|onclick="confirmRemovalOfFriends(form);"|, }), - subjectForm => WebGUI::Form::text($session, { name=>"subject" }), - sendMessageButton => WebGUI::Form::Submit($session, { value => $i18n->get('send message'), }), - messageForm => WebGUI::Form::textarea($session, { name=>"message" }), - formFooter => WebGUI::Form::formFooter($session), - ); - foreach my $userId (@{ $friends}) { - my $friend = WebGUI::User->new($session, $userId); - push(@{$var{friends}}, { - name => $friend->getWholeName, - profileUrl => $url->append($url->getRequestedUrl, 'op=viewProfile;uid='.$userId), - status => ($friend->isOnline ? $i18n->get('online') : $i18n->get('offline')), - checkboxForm => WebGUI::Form::checkbox($session, { name => 'userId', value => $userId, }), - }); - } - my $template = WebGUI::Asset->new( - $session, - $session->setting->get("manageFriendsTemplateId"), - "WebGUI::Asset::Template", - ); - return $style->userStyle($template->process(\%var)); -} - - -#------------------------------------------------------------------- - -=head2 www_removeFriends () - -Removes friends from the current user's friends list. - -=cut - -sub www_removeFriends { - my $session = shift; - return $session->privilege->insufficient() unless ($session->user->isRegistered); - my @users = $session->form->param("userId"); - WebGUI::Friends->new($session)->delete(\@users); - return www_manageFriends($session); -} - - -#------------------------------------------------------------------- - -=head2 www_sendMessageToFriends () - -Sends a message to selected friends. - -=cut - -sub www_sendMessageToFriends { - my $session = shift; - return $session->privilege->insufficient() unless ($session->user->isRegistered); - my @users = $session->form->param("userId"); - my $friends = WebGUI::Friends->new($session); - $friends->sendMessage($session->form->process("subject", "text"), $session->form->process("message","textarea"), \@users); - return www_manageFriends($session); + my $instance = WebGUI::Content::Account->createInstance($session,"friends"); + return $instance->displayContent($instance->callMethod("view")); } 1; diff --git a/lib/WebGUI/Operation/Inbox.pm b/lib/WebGUI/Operation/Inbox.pm index c0356f564..b33855295 100644 --- a/lib/WebGUI/Operation/Inbox.pm +++ b/lib/WebGUI/Operation/Inbox.pm @@ -11,15 +11,11 @@ package WebGUI::Operation::Inbox; #------------------------------------------------------------------- use strict qw(vars subs); -use URI; -use WebGUI::Inbox; +use WebGUI::Content::Account; +use WebGUI::Inbox::Message; use WebGUI::International; -use WebGUI::Paginator; -use WebGUI::SQL; -use WebGUI::Asset::Template; use WebGUI::User; use WebGUI::Utility; -use WebGUI::Operation::Shared; =head1 NAME @@ -37,6 +33,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 +54,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) { @@ -80,22 +75,23 @@ sub _appendPrivateMessageForm { name=>"message", 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 = ""; + if($form->get("messageId")) { + $messageId = $form->get("messageId"); + } + elsif(defined $message) { + $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,{}); $vars->{ submit_label } = $i18n->get("private message submit label"); $vars->{ form_footer } = WebGUI::Form::formFooter($session, {}); - - } #------------------------------------------------------------------- @@ -104,326 +100,58 @@ sub _appendPrivateMessageForm { returns a hashref with internationalized values for message status. +DEPRECATED: Do not use this method in new code. 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); } #------------------------------------------------------------------- =head2 www_sendPrivateMessage ( ) -Form for sending private messages +DEPRECATED: See WebGUI::Account::Inbox::sendMessage =cut sub www_sendPrivateMessage { - my $session = shift; - return $session->privilege->insufficient() unless ($session->user->isRegistered); - - my $i18n = WebGUI::International->new($session); - my $form = $session->form; - my $user = $session->user; - my $style = $session->style; - my $settings = $session->setting; - - my $templateId = $settings->get("sendPrivateMessageTemplateId"); - my $uid = $form->get("uid"); - my $userTo = WebGUI::User->new($session,$uid); - - my $vars = {}; - $vars->{title} = $i18n->get('private message title'); - - if($uid eq "") { - $vars->{'error_msg'} = $i18n->get('private message no user'); - return $style->userStyle(WebGUI::Asset::Template->new($session,$templateId)->process($vars)); - - } - elsif($uid eq $user->userId) { - $vars->{'error_msg'} = $i18n->get('private message no self error'); - return $style->userStyle(WebGUI::Asset::Template->new($session,$templateId)->process($vars)); - } - - unless($userTo->acceptsPrivateMessages($user->userId)) { - $vars->{'error_msg'} = $i18n->get('private message blocked error'); - return $style->userStyle(WebGUI::Asset::Template->new($session,$templateId)->process($vars)); - } - - _appendPrivateMessageForm($session,$vars,$userTo); - - $vars->{ accountOptions } = WebGUI::Operation::Shared::accountOptions($session); - - return $style->userStyle(WebGUI::Asset::Template->new($session,$templateId)->process($vars)); + my $session = shift; + my $uid = $session->form->get("uid"); + my $instance = WebGUI::Content::Account->createInstance($session,"inbox"); + return $instance->displayContent($instance->callMethod("sendMessage",[],$uid)); } -#------------------------------------------------------------------- - -=head2 www_sendPrivateMessageSave ( ) - -Post process the form, check for required fields, handle inviting users who are already -members (determined by email address) and send the email. - -=cut - -sub www_sendPrivateMessageSave { - my $session = shift; - return $session->privilege->insufficient() unless ($session->user->isRegistered); - - my $i18n = WebGUI::International->new($session); - my $form = $session->form; - my $user = $session->user; - my $style = $session->style; - - my $uid = $form->get("uid"); - my $userTo = WebGUI::User->new($session,$uid); - - if($uid eq "") { - my $output = sprintf qq|

    %s

    \n

    %s

    %s|, - $i18n->get('private message error'), - $i18n->get('private message no user'), - $session->url->getBackToSiteURL(), - $i18n->get('493', 'WebGUI'); - return $style->userStyle($output); - } elsif($uid eq $user->userId) { - my $output = sprintf qq|

    %s

    \n

    %s

    %s|, - $i18n->get('private message error'), - $i18n->get('private message no self error'), - $session->url->getBackToSiteURL(), - $i18n->get('493', 'WebGUI'); - return $style->userStyle($output); - } - - my $isReply = 0; - if($form->get("messageId")) { - my $message = WebGUI::Inbox->new($session)->getMessage($form->get("messageId")); - # Ensure that the user sending the message was sent by the user being replied to - # and that the user reponding is the user the message was sent to - if($message->get("sentBy") eq $uid && $message->get("userId") eq $user->userId) { - $isReply = 1; - $message->setStatus("replied"); - } - } - - my $message = WebGUI::Inbox->new($session)->addPrivateMessage({ - message => $form->get("message"), - subject => $form->get("subject"), - userId => $uid, - status => 'unread', - sentBy => $user->userId - },$isReply); - - unless(defined $message) { - my $output = sprintf qq|

    %s

    \n

    %s

    %s|, - $i18n->get('private message error'), - $i18n->get('private message blocked error'), - $session->url->getBackToSiteURL(), - $i18n->get('493', 'WebGUI'); - return $style->userStyle($output); - } - - - my $output = sprintf qq!

    %s

    %s!, - $i18n->get('private message sent'), - $session->url->getBackToSiteURL(), - $i18n->get('493', 'WebGUI'); - return $session->style->userStyle($output); - -} - - #------------------------------------------------------------------- =head2 www_viewInbox ( ) -Templated display all messages for the current user. +DEPRECATED: See WebGUI::Account::Inbox::view =cut sub www_viewInbox { my $session = shift; - return $session->privilege->insufficient() unless ($session->user->isRegistered); - - my $i18n = WebGUI::International->new($session); - my $vars = {}; - my @msg = (); - my $rpp = 50; - - #Deal with page number - my $pn = $session->form->get("pn") || 1; - my $pn_url = ""; - $pn_url = ";pn=$pn"; - - #Deal with sort order - my $sortBy = $session->form->get("sortBy"); - my $sort_url = ""; - $sort_url = ";sortBy=$sortBy" if($sortBy); - - #Cache the base url - my $inboxUrl = $session->url->page('op=viewInbox'); - - $vars->{ title } = $i18n->get(159); - $vars->{'subject_label' } = $i18n->get(351); - $vars->{'subject_url' } = $inboxUrl.$pn_url.";sortBy=subject"; - - $vars->{'status_label' } = $i18n->get(553); - $vars->{'status_url' } = $inboxUrl.$pn_url.";sortBy=status"; - - $vars->{'from_label' } = $i18n->get("private message from label"); - $vars->{'from_url' } = $inboxUrl.$pn_url.";sortBy=sentBy"; - - $vars->{'dateStamp_label'} = $i18n->get(352); - $vars->{'dateStamp_url' } = $inboxUrl.$pn_url.";sortBy=dateStamp"; - - my $adminUser = WebGUI::User->new($session,3)->username; - my $messages = WebGUI::Inbox->new($session)->getMessagesForUser($session->user,$rpp,$pn,$sortBy); - foreach my $message (@$messages) { - next if($message->get('status') eq 'deleted'); - - my $hash = {}; - $hash->{ message_url } = $session->url->page('op=viewInboxMessage;messageId='.$message->getId); - $hash->{ subject } = $message->get("subject"); - $hash->{ status_class } = $message->get("status"); - $hash->{ status } = _status($session)->{$hash->{ status_class }}; - - #Get the username of the person who sent the message - my $sentBy = $message->get("sentBy"); - #Assume it's the admin user for speed purposes - admin user is cached above the loop - my $from = $adminUser; - #If it wasn't the admin user, get the username of the person who sent it - if($sentBy ne "3") { - my $u = WebGUI::User->new($session,$sentBy); - #If the user that sent the message is valid, get the username - #This case would happen if the user was deleted after sending a private message - if($u->isRegistered) { - $from = $u->username; - } - } - - $hash->{ from } = $from; - $hash->{ dateStamp } = $session->datetime->epochToHuman($message->get("dateStamp")); - push(@msg,$hash); - } - my $msgCount = scalar(@{$messages}); - - #Pagination has to exist on every page regardless if there are more messages or not. - if($pn > 1 ) { - $vars->{'prev_url' } = $inboxUrl.';pn='.($pn-1).$sort_url; - $vars->{'prev_label' } = $i18n->get("private message prev label"); - } - if (scalar(@msg) >= $rpp) { - $vars->{'next_url' } = $inboxUrl.';pn='.($pn+1).$sort_url; - $vars->{'next_label' } = $i18n->get("private message next label"); - } - - $vars->{'messages' } = \@msg; - $vars->{'noresults' } = $i18n->get(353) unless ($msgCount > 0); - $vars->{'accountOptions'} = WebGUI::Operation::Shared::accountOptions($session); - my $templateId = $session->setting->get("viewInboxTemplateId"); - return $session->style->userStyle(WebGUI::Asset::Template->new($session,$templateId)->process($vars)); -} - -#------------------------------------------------------------------- - -=head2 www_deletePrivateMessage ( ) - -Mark a private message in the inbox as deleted. - -=cut - -sub www_deletePrivateMessage { - my $session = shift; - return $session->privilege->insufficient() unless ($session->user->isRegistered); - - #Get the message - my $message = WebGUI::Inbox->new($session)->getMessage($session->form->param("messageId")); - if(defined $message) { - # set the message status to 'deleted' - $message->setStatus("deleted"); - } - return www_viewInbox($session); + my $instance = WebGUI::Content::Account->createInstance($session,"inbox"); + return $instance->displayContent($instance->callMethod("view")); } #------------------------------------------------------------------- =head2 www_viewInboxMessage ( ) +DEPRECATED: Use WebGUI::Account::Inbox + Templated display of a single message for the user. =cut sub www_viewInboxMessage { my $session = shift; - return $session->privilege->insufficient() unless ($session->user->isRegistered); - - #Get the message - my $message = WebGUI::Inbox->new($session)->getMessage($session->form->param("messageId")); - - #Make sure users can only read their own messages - my $userId = $message->get("userId"); - my $groupId = $message->get("groupId"); - return $session->privilege->insufficient() unless ( - $session->user->userId eq $userId - || (defined $groupId && $session->user->isInGroup($groupId)) - ); - - my $i18n = WebGUI::International->new($session); - my $vars = {}; - $vars->{ title } = $i18n->get("private message reply title"); - $vars->{ from_label } = $i18n->get("private message from label"); - $vars->{ date_label } = $i18n->get("private message date label"); - - - if (defined $message) { - my $origStatus = $message->get("status"); - $message->setStatus("read") if($origStatus eq "unread"); - $vars->{'message_subject' } = $message->get("subject"); - $vars->{'dateStamp'} =$session->datetime->epochToHuman($message->get("dateStamp")); - $vars->{'status' } = _status($session)->{$message->get("status")}; - $vars->{ message } = $message->get("message"); - $vars->{ delete_text } = $i18n->get("private message delete text"); - $vars->{ delete_url } = '?op=deletePrivateMessage;messageId=' . $message->getId; - unless ($vars->{message} =~ /\{message} =~ s/(http\S*)/\$1\<\/a\>/g; - } - unless ($vars->{message} =~ /\
    {message} =~ /\
    {message} =~ /\

    {message} =~ s/\n/\
    \n/g; - } - - #Get the username of the person who sent the message - my $sentBy = $message->get("sentBy"); - #Assume it's the admin user who sent the message - my $from = WebGUI::User->new($session,3)->username; - #If the user actually exists, get the username - if($sentBy ne "1" && $sentBy ne "3") { - $from = WebGUI::User->new($session,$sentBy)->username; - } - - $vars->{ from } = $from; - - - #If the person didn't send the message to themselves (for admin only) and the user still exsists (check visitor case) - if($sentBy ne $session->user->userId && - $sentBy ne "1" && - $origStatus ne "pending" && - $origStatus ne "completed") { - my $u = WebGUI::User->new($session,$sentBy); - $vars->{'canReply'} = "true"; - _appendPrivateMessageForm($session,$vars,$u,$message); - } - - } - $vars->{'accountOptions'} = WebGUI::Operation::Shared::accountOptions($session); - my $templateId = $session->setting->get("viewInboxMessageTemplateId"); - return $session->style->userStyle(WebGUI::Asset::Template->new($session,$templateId)->process($vars)); + my $instance = WebGUI::Content::Account->createInstance($session,"inbox"); + return $instance->displayContent($instance->callMethod("viewMessage")); } -1; +1; \ No newline at end of file diff --git a/lib/WebGUI/Operation/Profile.pm b/lib/WebGUI/Operation/Profile.pm index bfa3b8c72..be0dd9166 100644 --- a/lib/WebGUI/Operation/Profile.pm +++ b/lib/WebGUI/Operation/Profile.pm @@ -11,19 +11,11 @@ package WebGUI::Operation::Profile; #------------------------------------------------------------------- use strict qw(vars subs); -use URI; -use WebGUI::Asset::Template; -use WebGUI::Operation::Auth; -use WebGUI::HTML; -use WebGUI::HTMLForm; +use WebGUI::Content::Account; use WebGUI::International; -use WebGUI::SQL; +use WebGUI::ProfileField; use WebGUI::User; use WebGUI::Utility; -use WebGUI::ProfileField; -use WebGUI::ProfileCategory; -use WebGUI::Operation::Shared; -use WebGUI::Operation::Friends; =head1 NAME @@ -46,7 +38,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 +72,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 @@ -89,12 +84,9 @@ email address to check for duplication sub isDuplicateEmail { my $session = shift; my $email = shift; - my ($otherEmail) - = $session->db->quickArray( - 'select count(*) from userProfileData where email = ? and userId <> ?', - [$email, $session->user->userId] - ); - return ($otherEmail > 0); + + my $field = WebGUI::ProfileField->new($session,'email'); + return $field->isDuplicate($email); } #------------------------------------------------------------------- @@ -103,6 +95,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 updateProfileFields method in WebGUI::User + =head3 session WebGUI session object @@ -119,12 +114,9 @@ Hash ref of profile data to save. sub saveProfileFields { my $session = shift; - my $u = shift; + my $u = shift; my $profile = shift; - - foreach my $fieldName (keys %{$profile}) { - $u->profileField($fieldName,${$profile}{$fieldName}); - } + $u->updateProfileFields($profile); } #------------------------------------------------------------------- @@ -134,6 +126,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 validateProfileDataFromForm method from WebGUI::User instead + There are two levels of validation: =over 4 @@ -152,46 +147,35 @@ warning if it is a duplicate. =cut sub validateProfileData { - my $session = shift; - my $opts = shift || {}; - my $regOnly = $opts->{regOnly}; - my %data = (); - my $error = ""; - my $warning = ""; - my $i18n = WebGUI::International->new($session); - my $fields = $regOnly ? WebGUI::ProfileField->getRegistrationFields($session) + my $session = shift; + my $opts = shift || {}; + my $regOnly = $opts->{regOnly}; + + my $error = ""; + my $warning = ""; + my $fields = $regOnly ? WebGUI::ProfileField->getRegistrationFields($session) : WebGUI::ProfileField->getEditableFields($session); - foreach my $field (@$fields) { - my $fieldValue = $field->formProcess; - if (ref $fieldValue eq "ARRAY") { - $data{$field->getId} = $$fieldValue[0]; - } else { - $data{$field->getId} = $fieldValue; - } - if ($field->isRequired && $data{$field->getId} eq "") { - $error .= '

  • '.$field->getLabel.' '.$i18n->get(451).'
  • '; - } elsif ($field->getId eq "email" && isDuplicateEmail($session,$data{$field->getId}) && WebGUI::ProfileField->new($session, "email")->isRequired() ) { - $warning .= '
  • '.$i18n->get(1072).'
  • '; - } - if ($field->getId eq "language" && $fieldValue ne "") { - unless (exists $i18n->getLanguages()->{$fieldValue}) { - $error .= '
  • '.$field->getLabel.' '.$i18n->get(451).'
  • '; - } - } - } - return (\%data, $error, $warning); + + my $retHash = $session->user->validateProfileDataFromForm($fields); + + my $warnings = $retHash->{warnings}; + my $errors = $retHash->{errors}; + + my $format = "
  • %s
  • "; + my $warning = ""; + my $error = ""; + map { $warning .= sprintf($format,$_) }@{$warnings}; + map { $error .= sprintf($format,$_) }@{$errors}; + + return ($retHash->{profile},$error,$warning); } #------------------------------------------------------------------- =head2 www_editProfile ( session ) -Provide a form where user profile data can be entered or edited. The subroutine -makes a large set of template variables which are passed to a template for presentation -and styling. The default template is PBtmpl0000000000000051 and is not user -selectable. - -Calls www_editProfileSave on submission. +DEPRECATED - This method is deprecated, and should not be used in new code. +Use WebGUI::Account::Profile::www_edit =head3 session @@ -200,86 +184,18 @@ A reference to the current session. =cut sub www_editProfile { - my $session = shift; - return WebGUI::Operation::Auth::www_auth($session,"init") if($session->user->isVisitor); - my $i18n = WebGUI::International->new($session); - my $vars = {}; - $vars->{displayTitle} .= $i18n->get(338); - $vars->{'profile.message'} = $_[0] if($_[0]); - $vars->{'profile.form.header'} = "\n\n".WebGUI::Form::formHeader($session,{}); - $vars->{'profile.form.footer'} = WebGUI::Form::formFooter($session,); - - $vars->{'profile.form.hidden'} = WebGUI::Form::hidden($session,{"name"=>"op","value"=>"editProfileSave"}); - $vars->{'profile.form.hidden'} .= WebGUI::Form::hidden($session,{"name"=>"uid","value"=>$session->user->userId}); - my @array = (); - foreach my $category (@{WebGUI::ProfileCategory->getCategories($session)}) { - next unless $category->isEditable; - my @temp = (); - foreach my $field (@{$category->getFields}) { - next unless ($field->isEditable); - next if $field->getId =~ /contentPositions/; - push(@temp, { - 'profile.form.element' => $field->formField, - 'profile.form.element.label' => $field->getLabel, - 'profile.form.element.subtext' => $field->isRequired ? "*" : undef, - 'profile.form.element.extras' => $field->getExtras, - }); - } - push(@array, { - 'profile.form.category' => $category->getLabel, - 'profile.form.category.loop' => \@temp - }); - } - $vars->{'profile.form.elements'} = \@array; - $vars->{'profile.form.submit'} = WebGUI::Form::submit($session,{}); - $vars->{'profile.form.cancel'} = WebGUI::Form::button($session,{ - value => $i18n->get('cancel'), - extras=>q|onclick="history.go(-1);" class="backwardButton"|, - }); - $vars->{'profile.accountOptions'} = WebGUI::Operation::Shared::accountOptions($session); - return $session->style->userStyle(WebGUI::Asset::Template->new($session, $session->setting->get('editUserProfileTemplate'))->process($vars)); + my $session = shift; + my $instance = WebGUI::Content::Account->createInstance($session,"profile"); + return $instance->displayContent($instance->callMethod("edit")); } -#------------------------------------------------------------------- - -=head2 www_editProfileSave ( session ) - -Validates all data submitted by www_editProfile. If errors or warnings are present, -they are concatenated and sent back to www_editProfile for display and to let the user -correct their mistakes. - -If no mistakes are present, saves the data to the user's profile, updates the session user -object. - -Returns the user to WebGUI::Operation::Auth::www_auth when done. - -=head3 session - -A reference to the current session. - -=cut - -sub www_editProfileSave { - my $session = shift; - my ($profile, $error, $warning); - return WebGUI::Operation::Auth::www_auth($session, "init") if ($session->user->isVisitor); - ($profile, $error, $warning) = validateProfileData($session); - $error .= $warning; - return www_editProfile($session, '
      '.$error.'
    ') if($error ne ""); - foreach my $fieldName (keys %{$profile}) { - $session->user->profileField($fieldName,$profile->{$fieldName}); - } - return WebGUI::Operation::Auth::www_auth($session); -} #------------------------------------------------------------------- =head2 www_viewProfile ( session ) -View the profile data for a user by the userId specified by the form variable C. -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: This method is deprecated, and should not be used in new code. +Use WebGUI::Account::Profile::www_view =head3 session @@ -288,47 +204,11 @@ A reference to the current session. =cut sub www_viewProfile { - my $session = shift; - my $u = WebGUI::User->new($session,$session->form->process("uid")); - my $i18n = WebGUI::International->new($session); - my $vars = {}; - $vars->{displayTitle} = $i18n->get(347).' '.$u->username; - - return $session->privilege->notMember() if($u->username eq ""); - - 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); - - my @array = (); - foreach my $category (@{WebGUI::ProfileCategory->getCategories($session)}) { - next unless ($category->get("visible")); - push(@array, {'profile.category' => $category->getLabel}); - foreach my $field (@{$category->getFields}) { - next unless ($field->get("visible")); - next if ($field->get("fieldName") eq "email" && !$u->profileField("publicEmail")); - push @array, { - 'profile.label' => $field->getLabel, - 'profile.value' => $field->formField(undef,2,$u), - 'profile.extras' => $field->getExtras, - }; - } - } - $vars->{'profile.elements'} = \@array; - - if ($session->user->userId eq $session->form->process("uid")) { - $vars->{'profile.accountOptions'} = WebGUI::Operation::Shared::accountOptions($session); - } - else { - ## TODO: Make this more legible code, maybe refactor into a method - push @{$vars->{'profile.accountOptions'}}, { - 'options.display' => '
    userId).'">'.$i18n->get('add to friends list', 'Friends').'', - }, { - 'options.display' => ''.$i18n->get('send private message').'', - }; - } - - return $session->style->userStyle(WebGUI::Asset::Template->new($session, $session->setting->get('viewUserProfileTemplate'))->process($vars)); + my $session = shift; + my $uid = $session->form->process("uid"); + my $instance = WebGUI::Content::Account->createInstance($session,"profile"); + return $instance->displayContent($instance->callMethod("view",[],$uid)); } -1; +1; \ No newline at end of file diff --git a/lib/WebGUI/Operation/ProfileSettings.pm b/lib/WebGUI/Operation/ProfileSettings.pm index 92644dffa..6fc856ce7 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 745d1dfa2..ac5578d08 100755 --- a/lib/WebGUI/Operation/Settings.pm +++ b/lib/WebGUI/Operation/Settings.pm @@ -241,33 +241,6 @@ sub definition { defaultValue=>$setting->get("AdminConsoleTemplate") }); # messaging settings - push(@fields, { - tab=>"messaging", - fieldType=>"template", - name=>"viewInboxTemplateId", - label=>$i18n->get('view inbox template'), - hoverHelp=>$i18n->get('view inbox template description'), - namespace=>"Inbox", - defaultValue=>$setting->get("viewInboxTemplateId"), - }); - push(@fields, { - tab=>"messaging", - fieldType=>"template", - name=>"viewInboxMessageTemplateId", - label=>$i18n->get('view inbox message template'), - hoverHelp=>$i18n->get('view inbox message template description'), - namespace=>"Inbox/Message", - defaultValue=>$setting->get("viewInboxMessageTemplateId"), - }); - push(@fields, { - tab=>"messaging", - fieldType=>"template", - name=>"sendPrivateMessageTemplateId", - label=>$i18n->get('send private message template'), - hoverHelp=>$i18n->get('send private message template description'), - namespace=>"Inbox/SendPrivateMessage", - defaultValue=>$setting->get("sendPrivateMessageTemplateId"), - }); push(@fields, { tab=>"messaging", fieldType=>"text", @@ -458,15 +431,6 @@ sub definition { namespace=>"userInvite/Email", defaultValue=>$setting->get("userInvitationsEmailTemplateId"), }); - push(@fields, { - tab => "user", - fieldType => "template", - defaultValue => "managefriends_________", - namespace => "friends/manage", - name => "manageFriendsTemplateId", - label => $i18n->get("manage friends template", "Friends"), - hoverHelp => $i18n->get("manage friends template help", "Friends"), - }); push @fields, { tab => "user", name => "showMessageOnLogin", @@ -498,24 +462,6 @@ sub definition { label => $i18n->get( 'showMessageOnLoginBody label' ), hoverHelp => $i18n->get( 'showMessageOnLoginBody description' ), defaultValue => $setting->get('showMessageOnLoginBody'), - }; - push @fields, { - tab => "user", - name => 'viewUserProfileTemplate', - fieldType => 'template', - namespace => 'Operation/Profile/View', - label => $i18n->get( 'user profile view template' ), - hoverHelp => $i18n->get( 'user profile view template description' ), - defaultValue => $setting->get('viewUserProfileTemplate'), - }; - push @fields, { - tab => "user", - name => 'editUserProfileTemplate', - fieldType => 'template', - namespace => 'Operation/Profile/Edit', - label => $i18n->get( 'user profile edit template' ), - hoverHelp => $i18n->get( 'user profile edit template description' ), - defaultValue => $setting->get('editUserProfileTemplate'), }; # auth settings my $options; @@ -618,6 +564,7 @@ sub www_editSettings { ui => { label => $i18n->get("ui") }, messaging => { label => $i18n->get("messaging") }, misc => { label => $i18n->get("misc") }, + account => { label => $i18n->get("account settings tab")}, user => { label => $i18n->get("user") }, auth => { label => $i18n->get("authentication") }, perms => { label => $i18n->get("permissions") }, @@ -643,6 +590,38 @@ sub www_editSettings { $tabform->getTab("auth")->fieldSetEnd; } + # Get fieldsets for avaiable account methods + 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 ( $@ ) { + $session->log->warn("Could not instantiate account pluggin $className...skipping"); + next; + } + + #Get the content of the settings form from the instance + my $settingsForm = eval { $instance->editSettingsForm }; + if( $@ ) { + $session->log->warn("Error calling editSettingsForm in $className...skipping : ".$@); + next; + } + + #If editUserSettingsForm is empty, skip it + next if $settingsForm eq ""; + + #Set the title of the fieldset + my $title = $account->{title}; + WebGUI::Macro::process($title); + + #Print the settings form for this account pluggin + $tabform->getTab("account")->fieldSetStart($title); + $tabform->getTab("account")->raw($settingsForm); + $tabform->getTab("account")->fieldSetEnd; + } + $tabform->submit(); $output .= $tabform->print; @@ -682,6 +661,26 @@ 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 + eval { $instance->editSettingsFormSave }; + + if( my $e = WebGUI::Error->caught ) { + $session->log->warn("Error calling editSettingsFormSave in $className...skipping : ".$e->error); + next; + } + } + ### Handle special settings # Reset login message seen numbers if ( $session->form->get( 'showMessageOnLoginReset' ) ) { diff --git a/lib/WebGUI/Operation/Shared.pm b/lib/WebGUI/Operation/Shared.pm index f2354d022..997f73c95 100644 --- a/lib/WebGUI/Operation/Shared.pm +++ b/lib/WebGUI/Operation/Shared.pm @@ -27,73 +27,19 @@ Shared routines for WebGUI Operations. TODO: DOCUMENT ME +DEPRECATED - USE WebGUI::Account->appendAccountOptions + =cut #------------------------------------------------------------------- sub accountOptions { my $session = shift; - my $i18n = WebGUI::International->new($session); - my @array; - my $op = $session->form->process("op"); - if ($session->user->isInGroup(12)) { - my %hash; - if ($session->var->isAdminOn) { - $hash{'options.display'} .= ''.$i18n->get(12).''; - } else { - $hash{'options.display'} .= ''.$i18n->get(63).''; - } - push(@array,\%hash); - } - unless ($op eq "displayAccount"){ - my %hash; - $hash{'options.display'} = ''.$i18n->get(342).''; - push(@array,\%hash); - } - unless ($op eq "editProfile"){ - my %hash; - $hash{'options.display'} = ''.$i18n->get(341).''; - push(@array,\%hash); - } - unless ($op eq "viewProfile"){ - my %hash; - $hash{'options.display'} = ''.$i18n->get(343).''; - push(@array,\%hash); - } - unless ($op eq "viewInbox"){ - my %hash; - $hash{'options.display'} = ''.$i18n->get(354).''; - push(@array,\%hash); - } - push(@array, {'options.display' => ''.$i18n->get('my purchases', 'Shop').''}); - - if ($session->setting->get('userInvitationsEnabled')) { - push @array, { - 'options.display' => sprintf('%s', $session->url->page('op=inviteUser'), $i18n->get('invite a friend')), - }; - } - unless ($op eq "manageFriends") { - push @array, { - 'options.display' => sprintf('%s', $session->url->page('op=manageFriends'), $i18n->get('see my friends', 'Friends')), - }; - } - my %logout; - $logout{'options.display'} = ''.$i18n->get(64).''; - push(@array,\%logout); - if ($session->setting->get("selfDeactivation") && !$session->user->isAdmin){ - my %hash; - $hash{'options.display'} = ''.$i18n->get(65).''; - push(@array,\%hash); - } - { ##Return to site link - my %hash; - $hash{'options.display'} = ''.$i18n->get(493).''; - push(@array,\%hash); - } - - return \@array; -} + my $vars = {}; + WebGUI::Account->appendAccountLinks($session,$vars); + return $vars->{'account.options'}; +} =head2 secureEval ( $session, $code ) diff --git a/lib/WebGUI/Paginator.pm b/lib/WebGUI/Paginator.pm index 45111c606..a10235746 100644 --- a/lib/WebGUI/Paginator.pm +++ b/lib/WebGUI/Paginator.pm @@ -483,9 +483,10 @@ sub getPageLinks { if ($i+1 == $pn) { push @pages, $i+1; push @pages_loop, { - "pagination.url" => '', - "pagination.text" => $i+1, - 'pagination.range' => ($first+1) . "-" . ($last+1), + "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 25dcc28c7..7126e9acd 100755 --- a/lib/WebGUI/ProfileField.pm +++ b/lib/WebGUI/ProfileField.pm @@ -266,20 +266,31 @@ sub formField { } } - #------------------------------------------------------------------- -=head2 formProcess ( ) +=head2 formProcess ( [ user ] ) Returns the value retrieved from a form post. +=head3 user + +optional user object to process properteis for. If no use is passed +in the current user will be used + =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)"); } #------------------------------------------------------------------- @@ -467,6 +479,29 @@ 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->quickScalar($sql,[$value, $session->user->userId]); + return ($duplicate > 0); +} + +#------------------------------------------------------------------- + =head2 isEditable ( ) Returns a boolean indicating whether this field may be editable by a user. @@ -507,6 +542,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/Shop/Transaction.pm b/lib/WebGUI/Shop/Transaction.pm index c96ca22ed..faef22dac 100644 --- a/lib/WebGUI/Shop/Transaction.pm +++ b/lib/WebGUI/Shop/Transaction.pm @@ -526,7 +526,11 @@ Displays the default thank you page. sub thankYou { my ($self) = @_; my $i18n = WebGUI::International->new($self->session,'Shop'); - return $self->www_viewMy($self->session, $self, $i18n->get('thank you message')); + + #Otherwise wrap the template into the account layout + my $args = [$self,$i18n->get('thank you message')]; + my $instance = WebGUI::Content::Account->createInstance($self->session,"shop"); + return $instance->displayContent($instance->callMethod("viewTransaction",$args)); } diff --git a/lib/WebGUI/User.pm b/lib/WebGUI/User.pm index 9aae6efbb..dd92a243e 100644 --- a/lib/WebGUI/User.pm +++ b/lib/WebGUI/User.pm @@ -118,6 +118,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"); @@ -130,7 +133,37 @@ sub acceptsPrivateMessages { return $sentBy->isInGroup($friendsGroup->getId); } - return 1; + return 0; +} + +#------------------------------------------------------------------- + +=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 $session = $self->session; + 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 $me = WebGUI::Friends->new($session,$self); + my $friend = WebGUI::Friends->new($session,$user); + + return 0 if ($me->isFriend($user->userId)); #Already a friend + return 0 if ($me->isInvited($user->userId) || $friend->isInvited($self->userId)); #Invitation sent by one or the other + + return $self->profileField('ableToBeFriend'); #Return profile setting } #------------------------------------------------------------------- @@ -317,13 +350,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(); @@ -418,6 +450,30 @@ sub getGroupIdsRecursive { #------------------------------------------------------------------- +=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 ( ) Attempts to build the user's whole name from profile fields, and ultimately their alias and username if all else @@ -433,6 +489,20 @@ 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 { @@ -764,6 +834,36 @@ sub profileField { #------------------------------------------------------------------- +=head2 profileIsViewable ( user ) + +Returns whether or not the user's profile is viewable by the user passed in + +=head3 user + +The user to test to see if the profile is viewable for. If no user is passed in, +the current user in session will be tested + +=cut + +sub profileIsViewable { + my $self = shift; + my $user = shift || $self->session->user; + my $userId = $user->userId; + + return 0 if ($self->isVisitor); #Can't view visitor's profile + return 1 if ($self->userId eq $userId); #Users can always view their own profile + + my $profileSetting = $self->profileField('publicProfile'); + + return 0 if ($profileSetting eq "none"); + return 1 if ($profileSetting eq "all"); + + my $friendsGroup = $self->friends; + return $user->isInGroup($friendsGroup->getId); +} + +#------------------------------------------------------------------- + =head2 referringAffiliate ( [ value ] ) Returns the unique identifier of the affiliate that referred this user to the site. @@ -852,6 +952,27 @@ sub uncache { #------------------------------------------------------------------- +=head2 updateProfileFields ( profile ) + +Saves profile data to a user's profile. Does not validate any of the data. + +=head3 profile + +Hash ref of key/value pairs of data in the users's profile to update. + +=cut + +sub updateProfileFields { + my $self = shift; + my $profile = shift; + + foreach my $fieldName (keys %{$profile}) { + $self->profileField($fieldName,$profile->{$fieldName}); + } +} + +#------------------------------------------------------------------- + =head2 username ( [ value ] ) Returns the username. @@ -889,6 +1010,78 @@ sub userId { #------------------------------------------------------------------- +=head2 validateProfileDataFromForm ( fields ) + +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 fields + +An array reference of profile field Ids to validate. + +=cut + +sub validateProfileDataFromForm { + my $self = shift; + my $session = $self->session; + my $fields = shift; + + my $i18n = my $i18n = WebGUI::International->new($session); + + 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); + push (@{$errors}, sprintf($i18n->get("language not available 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(1072)); + push(@{$warnFields},$fieldId); + } + } + + return { + profile => $data, + errors => $errors, + warnings => $warnings, + errorCategory => $errorCat, + errorFields => $errorFields, + warningFields => $warnFields, + }; +} + +#------------------------------------------------------------------- + =head2 validUserId ( userId ) Returns true if the userId exists in the users table. diff --git a/lib/WebGUI/VersionTag.pm b/lib/WebGUI/VersionTag.pm index 2dd82b05f..05c5a7224 100755 --- a/lib/WebGUI/VersionTag.pm +++ b/lib/WebGUI/VersionTag.pm @@ -17,6 +17,7 @@ package WebGUI::VersionTag; use strict; use WebGUI::Asset; use WebGUI::Workflow::Instance; +use WebGUI::DateTime; =head1 NAME diff --git a/lib/WebGUI/i18n/English/Account.pm b/lib/WebGUI/i18n/English/Account.pm new file mode 100644 index 000000000..d43c2c618 --- /dev/null +++ b/lib/WebGUI/i18n/English/Account.pm @@ -0,0 +1,14 @@ +package WebGUI::i18n::English::Account_Profile; +use strict; + +our $I18N = { + + 'Error: Cannot instantiate template' => { + message => q{Error: Cannot instantiate template %s for class %s}, + lastUpdated => 1225724810, + context => q{Error message in Account.pm}, + }, + +}; + +1; diff --git a/lib/WebGUI/i18n/English/Account_Friends.pm b/lib/WebGUI/i18n/English/Account_Friends.pm new file mode 100644 index 000000000..3e757b109 --- /dev/null +++ b/lib/WebGUI/i18n/English/Account_Friends.pm @@ -0,0 +1,253 @@ +package WebGUI::i18n::English::Account_Friends; +use strict; + +our $I18N = { + + 'title' => { + message => q{Friends}, + lastUpdated => 1225724810, + context => q{Tab label for Friends Account pluggin}, + }, + + 'friends style template label' => { + message => q|Style Template|, + lastUpdated => 1119068809 + }, + + 'friends style template hoverHelp' => { + message => q|Select a style template from the list to enclose friends in.|, + lastUpdated => 1119068809 + }, + + 'friends layout template label' => { + message => q|Edit Layout Template|, + lastUpdated => 1119068809 + }, + + 'friends 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 + }, + + 'friends view template label' => { + message => q|View Template|, + lastUpdated => 1119068809 + }, + + 'friends view template hoverHelp' => { + message => q|Choose the main template for viewing friends|, + lastUpdated => 1119068809 + }, + + 'friends edit template label' => { + message => q|Edit Template|, + lastUpdated => 1119068809 + }, + + 'friends edit template hoverHelp' => { + message => q|Choose the template for editing friends|, + lastUpdated => 1119068809 + }, + + 'friends send request template label' => { + message => q|Send Friends Request Template|, + lastUpdated => 1119068809 + }, + + 'friends send request template hoverHelp' => { + message => q|Choose the template for sending friends requests|, + lastUpdated => 1119068809 + }, + + 'friends confirm template label' => { + message => q|Friends Request Confirm Template|, + lastUpdated => 1119068809 + }, + + 'friends confirm template hoverHelp' => { + message => q|Choose the template for displaying confirmation that a friends request has been sent|, + lastUpdated => 1119068809 + }, + + 'friends remove confirm template label' => { + message => q|Friends Removal Confirm Template|, + lastUpdated => 1119068809 + }, + + 'friends remove confirm template hoverHelp' => { + message => q|Choose the template for displaying confirmation that you wish to remove a friend|, + lastUpdated => 1119068809 + }, + + 'friends error template label' => { + message => q|Error Template|, + lastUpdated => 1119068809 + }, + + 'friends error template hoverHelp' => { + message => q|Choose the template for displaying friends errors|, + lastUpdated => 1119068809 + }, + + 'back label' => { + message => q{back to site}, + lastUpdated => 1119068809 + }, + + 'edit my profile' => { + message => q|edit my profile|, + lastUpdated => 1068703399 + }, + + 'profile as others label' => { + message => q{view my profile as others see it}, + lastUpdated => 1119068809 + }, + + 'error label' => { + message => q{Error}, + lastUpdated => 1225724810, + }, + + 'member since' => { + message => q{Member Since }, + lastUpdated => 1119068809 + }, + + 'add to network label' => { + message => q{Add to Network}, + lastUpdated => 1119068809 + }, + + 'back to profile label' => { + message => q{back to profile}, + lastUpdated => 1225724810, + }, + + 'adding user message' => { + message => q{You are adding %s to your network.}, + lastUpdated => 1225724810, + }, + + 'sending to message' => { + message => q{The following message will be sent along with your invitation:}, + lastUpdated => 1225724810, + }, + + 'default friend comments' => { + message => q{%s, +I'd like you to be a part of my friends network. + +Thanks, +%s}, + lastUpdated => 1225724810, + }, + + 'send invite button label' => { + message => q{Send Invitation}, + lastUpdated => 1225724810, + }, + + 'cancel button label' => { + message => q{Cancel}, + lastUpdated => 1225724810, + }, + + 'error user is already friend' => { + message => q{This user is already a member of your friends network}, + lastUpdated => 1181493546, + }, + + 'error user is already invited' => { + message => q{You have already sent an invitation for this user to join your friends network}, + lastUpdated => 1181493546, + }, + + 'does not want to be a friend' => { + message => q{This user prefers not to be added as a friend.}, + lastUpdated => 1186264488, + }, + + '' => { + message => q{}, + lastUpdated => 1225724810, + }, + + 'back to user profile' => { + message => q{back to users profile}, + lastUpdated => 1225724810, + }, + + 'message sent label' => { + message => q{Friends Request Sent}, + lastUpdated => 1181019679, + }, + + 'add to friends confirmation' => { + message => q{An email has been sent to %s for your request to be added to your friends network.}, + lastUpdated => 1186030776, + }, + + 'send private message label' => { + message => q{Send Private Message}, + lastUpdated => 1186030776, + }, + + 'send private message label' => { + message => q{Send Private Message}, + lastUpdated => 1186030776, + }, + + 'remove from friends label' => { + message => q{Remove From Friends}, + lastUpdated => 1186030776, + }, + + 'no friend selected' =>{ + message => q{You have not selected friend to be removed from your friends list}, + lastUpdated => 1186030776, + }, + + 'not a friend error' =>{ + message => q{The user you have selected to remove is not in your friends list.}, + lastUpdated => 1186030776, + }, + + 'remove confirm label' =>{ + message => q{Remove Friend Confirmation}, + lastUpdated => 1186030776, + }, + + 'remove confirm message' =>{ + message => q{Are you sure you want remove %s from your friends list?}, + lastUpdated => 1186030776, + }, + + 'remove confirm yes' =>{ + message => q{yes, remove this user}, + lastUpdated => 1186030776, + }, + + 'remove confirm no' =>{ + message => q{no, I made a mistake}, + lastUpdated => 1186030776, + }, + + 'friend removed' =>{ + message => q{%s was removed from your friends list}, + lastUpdated => 1186030776, + }, + + 'no access' =>{ + message => q{You do not have permission to view this user's friends list}, + lastUpdated => 1186030776, + }, + + 'friends is off' =>{ + message => q{You do not have friends enabled. In order to see this page you must edit your profile and enable the friends setting.}, + lastUpdated => 1186030776, + }, + +}; + +1; diff --git a/lib/WebGUI/i18n/English/Account_Inbox.pm b/lib/WebGUI/i18n/English/Account_Inbox.pm new file mode 100644 index 000000000..5de408122 --- /dev/null +++ b/lib/WebGUI/i18n/English/Account_Inbox.pm @@ -0,0 +1,360 @@ +package WebGUI::i18n::English::Account_Inbox; +use strict; + +our $I18N = { + + 'title' => { + message => q{Inbox}, + lastUpdated => 1225724810, + 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 confirm message template label' => { + message => q|Invitation Confirmation Message Template|, + lastUpdated => 1119068809 + }, + + 'invitation confirm message template hoverHelp' => { + message => q|Choose the template for viewing invitation confirmations|, + lastUpdated => 1119068809 + }, + + 'inbox view invitation template label' => { + message => q|View Invitation Template|, + lastUpdated => 1119068809 + }, + + 'inbox view invitation template hoverHelp' => { + message => q|Choose the template for viewing an invitation|, + 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, + }, + + 'error label' => { + message => q{Error}, + lastUpdated => 1225724810, + }, + + 'invitation label' => { + message => q{Invitation}, + lastUpdated => 1225724810, + }, + + 'invitation count' => { + message => q{invitations}, + lastUpdated => 1225724810, + }, + + 'invitation message' => { + message => q{%s has invited you to join their friends newtork}, + lastUpdated => 1225724810, + }, + + 'no invitations' => { + message => q{You have no outstanding friends invitations}, + lastUpdated => 1225724810, + }, + + 'accept button label' => { + message => q{Accept}, + lastUpdated => 1225724810, + }, + + 'deny button label' => { + message => q{Deny}, + lastUpdated => 1225724810, + }, + + 'invitation confirm label' => { + message => q{Invitation Notices Sent}, + lastUpdated => 1225724810, + }, + + 'invitation confirm message' => { + message => q{The following users were notified:}, + lastUpdated => 1225724810, + }, + + 'invitations back label' => { + message => q{back to invitations}, + lastUpdated => 1225724810, + }, + + 'invitation does not exist' => { + message => q{The invitation you are trying to view has already been approved or denied.}, + lastUpdated => 1119068809 + }, + + 'no access to invitation' => { + message => q{You do not have permission to view this invitation.}, + lastUpdated => 1119068809 + }, + + 'inviter no longer exists' => { + message => q{The user who sent this invitation is no longer a member of the site.}, + lastUpdated => 1119068809 + }, + + +}; + +1; diff --git a/lib/WebGUI/i18n/English/Account_Profile.pm b/lib/WebGUI/i18n/English/Account_Profile.pm new file mode 100644 index 000000000..22f952d89 --- /dev/null +++ b/lib/WebGUI/i18n/English/Account_Profile.pm @@ -0,0 +1,161 @@ +package WebGUI::i18n::English::Account_Profile; +use strict; + +our $I18N = { + + 'title' => { + message => q{Profile}, + lastUpdated => 1225724810, + context => q{Tab label for Profile Account pluggin}, + }, + + 'profile style template label' => { + message => q|Style Template|, + lastUpdated => 1119068809 + }, + + 'profile style template hoverHelp' => { + message => q|Select a style template from the list to enclose the inbox in.|, + lastUpdated => 1119068809 + }, + + 'profile layout template label' => { + 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 that are editable by the current user as well as the contents of the one currently chosen}, + lastUpdated => 1119068809 + }, + + 'profile view template label' => { + message => q|View Template|, + lastUpdated => 1119068809 + }, + + 'profile view template hoverHelp' => { + message => q|Choose the main template for viewing a profile|, + lastUpdated => 1119068809 + }, + + 'profile edit template label' => { + message => q|Edit Template|, + lastUpdated => 1119068809 + }, + + 'profile edit template hoverHelp' => { + 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 + }, + + 'profile error template label' => { + message => q|Error Template|, + lastUpdated => 1119068809 + }, + + 'profile error template hoverHelp' => { + message => q|Choose the template to use for displaying profile errors to the user|, + lastUpdated => 1119068809 + }, + + + '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{back to site}, + lastUpdated => 1119068809 + }, + + 'profile not public error' => { + message => q|This user's profile is not public.|, + lastUpdated => 1043881275 + }, + + 'friends only' => { + message => q|Your profile is viewable to Friends|, + lastUpdated => 1043881275 + }, + + 'private profile' => { + message => q|Your profile is Private|, + lastUpdated => 1043881275 + }, + + 'public profile' => { + message => q|Your profile is Public|, + lastUpdated => 1043881275 + }, + + 'private label' => { + message => q|Private|, + lastUpdated => 1043881275 + }, + + 'public label' => { + message => q|Public|, + lastUpdated => 1043881275 + }, + + 'friends only label' => { + message => q|Friends Only|, + lastUpdated => 1043881275 + }, + + 'error label' => { + message => q{Error}, + lastUpdated => 1225724810, + }, + + 'back to profile label' => { + message => q{back to profile}, + lastUpdated => 1225724810, + }, + + +}; + +1; diff --git a/lib/WebGUI/i18n/English/Account_Shop.pm b/lib/WebGUI/i18n/English/Account_Shop.pm new file mode 100644 index 000000000..d1671d31b --- /dev/null +++ b/lib/WebGUI/i18n/English/Account_Shop.pm @@ -0,0 +1,40 @@ +package WebGUI::i18n::English::Account_Shop; +use strict; + +our $I18N = { + + 'title' => { + message => q{Shop}, + lastUpdated => 1225724810, + context => q{Tab label for User Account pluggin}, + }, + + 'shop style template label' => { + message => q|Style Template|, + lastUpdated => 1119068809 + }, + + 'shop style template hoverHelp' => { + message => q|Select a style template from the list to enclose the shop tab in.|, + lastUpdated => 1119068809 + }, + + 'shop layout template label' => { + message => q|Layout Template|, + lastUpdated => 1119068809 + }, + + 'shop layout template hoverHelp' => { + message => q{Choose a layout template in which to enclose the content from the various methods within the shop tab}, + lastUpdated => 1119068809 + }, + + 'manage purchases label' => { + message => q{Manage Purchases}, + lastUpdated => 1119068809 + }, + + +}; + +1; diff --git a/lib/WebGUI/i18n/English/Account_User.pm b/lib/WebGUI/i18n/English/Account_User.pm new file mode 100644 index 000000000..b3163d192 --- /dev/null +++ b/lib/WebGUI/i18n/English/Account_User.pm @@ -0,0 +1,40 @@ +package WebGUI::i18n::English::Account_User; +use strict; + +our $I18N = { + + 'title' => { + message => q{Account}, + lastUpdated => 1225724810, + context => q{Tab label for User Account pluggin}, + }, + + 'user style template label' => { + message => q|Style Template|, + lastUpdated => 1119068809 + }, + + 'user style template hoverHelp' => { + message => q|Select a style template from the list to enclose the account tab in.|, + lastUpdated => 1119068809 + }, + + 'user layout template label' => { + message => q|Layout Template|, + lastUpdated => 1119068809 + }, + + 'user layout template hoverHelp' => { + message => q{Choose a layout template in which to enclose the content from the various methods within the account tab}, + lastUpdated => 1119068809 + }, + + 'templates in auth method message' => { + message => q{The display templates for this module can be found in the settings
    for the authentications modules you have installed on your site.
    }, + lastUpdated => 1119068809 + }, + + +}; + +1; diff --git a/lib/WebGUI/i18n/English/WebGUI.pm b/lib/WebGUI/i18n/English/WebGUI.pm index b1477ea56..d50b6512e 100755 --- 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 @@ -244,6 +249,16 @@ our $I18N = { context => q|Title of the statistics viewer for the admin console.| }, + 'required error' => { + message => q{%s is required.}, + lastUpdated => 1031514049 + }, + + 'language not available error' => { + message => q|%s is not available. Please select another language|, + lastUpdated => 1031514049 + }, + '451' => { message => q|is required.|, lastUpdated => 1031514049 @@ -325,7 +340,7 @@ our $I18N = { }, '861' => { - message => q|Make profile public?|, + message => q|Profile Privacy Setting|, lastUpdated => 1043879954 }, @@ -604,6 +619,11 @@ our $I18N = { lastUpdated => 1031514049 }, + 'demographic info short' => { + message => q|Demographic|, + lastUpdated => 1031514049 + }, + '77' => { message => q|That account name is already in use by another member of this site. Please try a different username. The following are some suggestions:
    %sToo
    @@ -835,6 +855,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 @@ -1248,6 +1273,11 @@ You must be using mod_perl and configure PerlSetEnv SYBASE /opt/sybase/11.0.2 lastUpdated => 1031514049 }, + 'misc info short' => { + message => q|Miscellaneous|, + lastUpdated => 1031514049 + }, + '967' => { message => q|Empty everyone's trash.|, lastUpdated => 1208022779 @@ -1516,6 +1546,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 +1941,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 +2287,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 @@ -3229,6 +3274,12 @@ a user.|, lastUpdated => 1118941685, }, + 'account settings tab' => { + message => q|Account|, + lastUpdated => 1098327046, + context => q|Tab label for the account settings in WebGUI Settings.| + }, + 'account' => { message => q|Account|, lastUpdated => 1098327046, @@ -3534,6 +3585,11 @@ LongTruncOk=1

    lastUpdated => 1181019679, }, + 'inbox message status active' => { + message => q|Active|, + lastUpdated => 1181019679, + }, + 'private message prev label' => { message => q|Previous|, lastUpdated => 1181019679, diff --git a/lib/WebGUI/i18n/English/WebGUIProfile.pm b/lib/WebGUI/i18n/English/WebGUIProfile.pm index 5d4e671d6..afed1aee5 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/t/Account.t b/t/Account.t new file mode 100644 index 000000000..7b67756d6 --- /dev/null +++ b/t/Account.t @@ -0,0 +1,76 @@ +# vim:syntax=perl +#------------------------------------------------------------------- +# WebGUI is Copyright 2001-2008 Plain Black Corporation. +#------------------------------------------------------------------- +# Please read the legal notices (docs/legal.txt) and the license +# (docs/license.txt) that came with this distribution before using +# this software. +#------------------------------------------------------------------ +# http://www.plainblack.com info@plainblack.com +#------------------------------------------------------------------ + +# This tests the operation of WebGUI::Account modules. You can use +# as a base to test your own modules. + +use FindBin; +use strict; +use lib "$FindBin::Bin/lib"; +use Test::More; +use WebGUI::Test; # Must use this before any other WebGUI modules +use WebGUI::Session; + +#---------------------------------------------------------------------------- +# Init +my $session = WebGUI::Test->session; + + +#---------------------------------------------------------------------------- +# Tests + +plan tests => 7; # Increment this number for each test you create + +#---------------------------------------------------------------------------- +# Test the creation of WebGUI::Account + +# Can we load WebGUI::Account? +use_ok( "WebGUI::Account" ); + +SKIP: { # Not everyone has Test::Exception yet + eval { require Test::Exception; import Test::Exception }; + # Skip 1 test if Test::Exception couldn't be loaded + skip 1, 'Test::Exception not found' if $@; + throws_ok( sub { WebGUI::Account->new }, 'WebGUI::Error::InvalidObject', + 'new() throws exception without session object' + ); +}; + +my $account; +# ok() tests booleans. assignment evaluates to the value assigned (it's how '$a = $b = 4' works) +ok( $account = WebGUI::Account->new( $session ), + "WebGUI::Account object created successfully" +); + +# Test $account->isa +isa_ok( $account, "WebGUI::Account", 'Blessed into the right class' ); + +#---------------------------------------------------------------------------- +# Test getUrl + +is( $account->getUrl, $session->url->page('op=account;module=;do='), + 'getUrl adds op, module, and do' +); + +is( $account->getUrl( 'foo=bar' ), $session->url->page( 'op=account;foo=bar' ), + 'getUrl adds op if passed other parameters' +); + +is( $account->getUrl( 'op=account' ), $session->url->page( 'op=account' ), + 'getUrl doesnt add op=account if already exists' +); + +#---------------------------------------------------------------------------- +# Cleanup +END { + +} +#vim:ft=perl 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 diff --git a/www/extras/account/account.css b/www/extras/account/account.css new file mode 100644 index 000000000..d75c73806 --- /dev/null +++ b/www/extras/account/account.css @@ -0,0 +1,724 @@ + +/* general */ + + body { + margin:0; + padding:0; + font: 11px Verdana; + } + a { + cursor: pointer; + } + button { + cursor: pointer; + } + img { + border: none; + } + .button { + float:right; + padding-right:10px; + } + .centered { + text-align: center; + } + .account_message { + width: 600px; + height: 300px; + border: solid #BECEF8 1px; + margin-left: 50px; + margin-bottom: 20px; + overflow:-moz-scrollbars-vertical; + overflow-x:hidden; + overflow-y:scroll; + background-color: white; + text-align: left; + } + .profileMember { + text-align:right; + margin-right:20px; + font-size:9px; + } + .member { + font: 9px Verdana, Arial, Helvetica, sans-serif; + color:#000000; + text-align:center; + } + .photostyle { + border:solid #9BB4F4 2px; + margin-bottom:5px; + margin-top:5px + } + #rightalign { + float: right; + } + /*.send { + padding-right: 75px; + }*/ + + .Profile_registration { + + } + .Profile_registration td { + font-size:9pt; + font-family:arial; + } + .Profile_registration .tabs a { + text-decoration:none; + background-color:#FEEBC7; + margin-right:10px; + padding:0px 10px 1px 10px; + color:#FDC55B; + font-weight:bold; + border:solid #FDBA42 1px; + } + .Profile_registration .tabs a.active { + background:#FDBA42; + color:black; + } + .Profile_registration .header { + font-size:10px; + font-weight:bold; + text-align:left; + color:#fff; + background-color:#818997; + border-top:solid #FE9515 3px; + text-align:right; + } + .Profile_registration .header a { + color:white; + text-decoration:none; + } + .Profile_registration .help a { + font-weight:bold; + text-decoration:none; + } + + .Profile_registration .inputText { + font-size:10px; + margin-right:1px; + } + .Profile_registration .label { + font-weight:bold; + font-size:9pt; + text-align:right; + white-space:nowrap; + width:1%; + } + .Profile_registration .labelLeft { + font-weight:bold; + font-size:9pt; + text-align:right; + white-space:nowrap; + width:1%; + text-align: left; + vertical-align: top; + } + .Profile_registration .smallLabel { + font-size:8px; + text-align:center; + } + .Profile_registration .smallText { + font-size:9px; + } + .Profile_registration .yourselfBG { + border:solid #CEDBF8 1px; + background-color:#EEF2FD; + color:black; + padding: 2px; + } + /*.Profile_registration .yourselfBG a { + font-weight:bold; + color:#0054ff; + text-decoration:none; + }*/ + .Profile_registration .bar { + background-color:#DDE6FB; + border:solid #BECEF8 1px; + text-align:center; + color:#0B2259; + font-size:14px; + font-weight:bold; + } + + .Profile_registration .bar a { + color:#0B2259; + font-size:10px; + font-weight:bold; + } + +/* profile errors */ + +#profileErrors { + background-color: #ff0000; + font-weight: bold; + color: #ffffff; + text-align: center; +} + +.profilefield_required_off { +} +.profilefield_required { + background-color: #ffffbb; +} +.profilefield_error { + background-color: #FF9494; +} + +/* bio, addtonetwork, network */ + + .bordered { + border-bottom: dashed #BECEF8 2px; + padding-bottom: 10px; + } + .friendpic { + border: solid #BECEF8 1px; + } + .invitemsg { + width: 600px; + height: 150px; + } + ol.Profile_interests { + font-size:15px; + font-weight:bold; + color:#0B2259; + list-style-type:none; + margin:0px; + padding:0px; + padding:5px 5px; + } + ol.Profile_interests li { + margin-bottom:15px; + } + ol.Profile_interests span { + font-weight:normal; + font-size:12px; + color:black; + } + .pBio { + border-bottom:solid #DDE6FB 1px; + margin:0px; + margin-bottom:5px; + padding-bottom:5px; + } + .pBio div { + background-color:#DDE6FB; + padding:2px 5px; + margin-bottom:2px; + } + .program { + font-size: 9px; + } + +/* edit box */ + + .editBox { + font-size:9px; + font-weight:bold; + background:white url(images/edit_box_bg.jpg) no-repeat bottom left; + border:solid #8DABF1 2px; + padding:5px; + width:590px; + -moz-box-sizing:border-box; + font-family:verdana; + z-index:100; + position:absolute; + top:100px; + left:100px; + display:block; + } + .editBox input, .editBox select { + font-size:9px; + } + +/* inbox */ + +.Profile_registration .inboxTitle { + background-color:#DDE6FB; + border:solid #BECEF8 1px; + text-align:center; + font-size:10px; + font-weight:bold; + color:#0B2259; + text-decoration: underline; +} + +/* inbox threads */ + + .evenThread { + background-color: #e1e8fb; + border-bottom: 1px solid #bfcef9; + padding: 4px; + text-align:center; + } + .oddThread { + background-color: #eef2fd; + border-bottom: 1px solid #bfcef9; + padding: 4px; + text-align: center; + } +/* inbox forms */ + +.inbox_from { + color: black; + text-decoration: none; + font-weight: normal; +} + +.inbox_subject { + width: 530px; +} + +.inbox_messageTo { + width: 530px; + height: 50px; + border: solid #BECEF8 1px; + overflow:-moz-scrollbars-vertical; + overflow-x:hidden; + overflow-y:scroll; + background-color: white; +} + +/* inbox contacts */ + .datacells { + border-bottom: dashed #BECEF8 1px; + } + .inbox_contactsTbl { + font-size:9pt; + font-family:arial; + background-color:#EEF2FD; + } + #contacts { + height: 275px; + overflow: auto; + } + +/* pagination */ +.Profile_pagination { + text-align:right; + font-size:10px; +} +.Profile_pagination a { + font-weight:bold; + font-size:10px; + border:solid #BECEF8 1px; + padding:1px 5px; + text-decoration:none; + background-color:#EEF2FD; +} + +.Profile_pagination a:hover { + background-color:#FE9515; + color:white; +} + +.Profile_pagination .prevNext { + border: none; + background-color: transparent; + color: black; +} + +.Profile_pagination .prevNext:hover { + border: none; + background-color: transparent; + color: black; +} + +.Profile_pagination .active { + font-weight:bold; + font-size:10px; + border:solid #BECEF8 1px; + padding:1px 5px; + text-decoration:none; + background-color:#FE9515; + color:white; +} + +/* TABS - outer */ + +.bottombutton { + border: none; + float:right; + padding-right:2px; + padding-top: 2px; + position: relative; +} +.content { + padding:10px; + +} +.subContent { + border: solid #ffa700 6px; +} +.topbutton { + border: none; + float:right; + clear:both; + padding-right:2px; + padding-top: 2px; + position: relative; +} + +ul.topTabs, +ul.topTabs li { + margin:0px; + padding:0px; + list-style-type:none; + position:relative;zoom:1; + width:auto; + + Xposition:relative; +} +ul.topTabs li { + display:block; + float:left; + margin-right: 5px; +} +ul.topTabs li b { + display:block; + position:relative; + top:-1px; + border-top:solid #ffa700 1px; + background-color: #faee9a; + padding:4px 8px; +} +ul.topTabs a { + display:block; + color:#ffa700; + font-size:12px; + font-family: Arial, Helvetica, sans-serif; + text-decoration:none; + background-color:#faee9a; + border-left: solid #ffa700 1px; + border-right: solid #ffa700 1px; +} +ul.topTabs a:hover, +ul.topTabs a:hover b, +ul.topTabs a.selected, +ul.topTabs a.selected b { + background-color:#ffa700; + color:#fff; +} + +/* TABS - YUI */ + +.cleardiv { + clear: both; + margin: 0px 0px 0px 0px; + padding: 0px; +} + +.view { + border: none; + font: bold 10px Verdana; + color: #0b2258; + text-decoration:none; + position: absolute; + right: 4px; + top:4px; +} + +.profile_displayView { + -x-system-font:none; + border:medium none; + color:#0B2258; + display:inline; + float:right; + font-family:Verdana; + font-size:10px; + font-size-adjust:none; + font-stretch:normal; + font-style:normal; + font-variant:normal; + font-weight:bold; + line-height:normal; + padding-right:8px; + padding-top:3px; +} + +.profile_displaySubContent { + border: solid #ffa700 6px; + border-top: solid #ffa700 18px; +} + +/* view profile */ + +.profile_fieldLabel { +background: #DDE6FB; +border: 1px solid white; +} +.profile_fieldData { +margin-left: 5px; +} + + /* +Copyright (c) 2008, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.net/yui/license.txt +version: 2.6.0 +*/ +/* .yui-navset defaults to .yui-navset-top */ +.yui-skin-sam .yui-navset .yui-nav, +.yui-skin-sam .yui-navset .yui-navset-top .yui-nav { /* protect nested tabviews from other orientations */ + border:solid #eef2fd; /* color between tab list and content */ + border-width:0 0 5px; + Xposition:relative; + zoom:1; +} + +.yui-skin-sam .yui-navset .yui-nav li, +.yui-skin-sam .yui-navset .yui-navset-top .yui-nav li { + margin:0 0.3em 0 0; /* space between tabs */ + padding:5px 0 0; /* gecko: make room for overflow */ + zoom:1; +} + +.yui-skin-sam .yui-navset .yui-nav .selected, +.yui-skin-sam .yui-navset .yui-navset-top .yui-nav .selected { + margin:0 0.3em -1px 0; /* for overlap */ +} + +.yui-skin-sam .yui-navset .yui-nav a, +.yui-skin-sam .yui-navset .yui-navset-top .yui-nav a { + background:#9bb4f4; /* tab background */ + border:solid #eef2fd; + border-width:0 1px; + color:#eef2fd; + position:relative; + text-decoration:none; + font-size:12px; + font-family: Arial, Helvetica, sans-serif; + font-weight: bold; +} + +.yui-skin-sam .yui-navset .yui-nav a em, +.yui-skin-sam .yui-navset .yui-navset-top .yui-nav a em { + border:solid #eef2fd; + border-width:1px 0 0; + cursor:hand; + padding:0.25em .75em; + left:0; right: 0; bottom: 0; /* protect from other orientations */ + top:-1px; /* for 1px rounded corners */ + position:relative; +} + +.yui-skin-sam .yui-navset .yui-nav .selected a, +.yui-skin-sam .yui-navset .yui-nav .selected a:focus, /* no focus effect for selected */ +.yui-skin-sam .yui-navset .yui-nav .selected a:hover { /* no hover effect for selected */ + background:#eef2fd; /* selected tab background */ + color:#0a2359; + font-size:12px; + font-family: Arial, Helvetica, sans-serif; + text-decoration:none; + font-weight: bold; +} + +.yui-skin-sam .yui-navset .yui-nav a:hover, +.yui-skin-sam .yui-navset .yui-nav a:focus { + background:#eef2fd; /* selected tab background */ + color:#0a2359; + outline:0; + font-size:12px; + font-family: Arial, Helvetica, sans-serif; + text-decoration:none; + font-weight: bold; + +} + +.yui-skin-sam .yui-navset .yui-nav .selected a, +.yui-skin-sam .yui-navset .yui-nav .selected a em { + border-color:#eef2fd; /* selected tab border color */ +} + +.yui-skin-sam .yui-navset .yui-content { + background:#edf5ff; /* content background color */ +} + +.yui-skin-sam .yui-navset .yui-content, +.yui-skin-sam .yui-navset .yui-navset-top .yui-content { + border:5px solid #eef2fd; /* content border */ + padding:0.75em 1em; /* content padding */ +} + +/* left and right orientations */ +.yui-skin-sam .yui-navset-left .yui-nav, +.yui-skin-sam .yui-navset .yui-navset-left .yui-nav, +.yui-skin-sam .yui-navset .yui-navset-right .yui-nav, +.yui-skin-sam .yui-navset-right .yui-nav { + border-width:0 5px 0 0; + Xposition:absolute; /* from tabview-core; have to reiterate for skin-sam due to pos:rel on skin-sam yui-nav */ + top:0; bottom:0; /* stretch to fill content height */ +} + +.yui-skin-sam .yui-navset .yui-navset-right .yui-nav, +.yui-skin-sam .yui-navset-right .yui-nav { + border-width:0 0 0 5px; +} + +.yui-skin-sam .yui-navset-left .yui-nav li, +.yui-skin-sam .yui-navset .yui-navset-left .yui-nav li, +.yui-skin-sam .yui-navset-right .yui-nav li { + margin:0 0 0.3em; /* space between tabs */ + padding:0 0 0 1px; /* gecko: make room for overflow */ +} + +.yui-skin-sam .yui-navset-right .yui-nav li { + padding:0 1px 0 0; /* gecko: make room for overflow */ +} + +.yui-skin-sam .yui-navset-left .yui-nav .selected, +.yui-skin-sam .yui-navset .yui-navset-left .yui-nav .selected { + margin:0 -1px 0.16em 0; +} + +.yui-skin-sam .yui-navset-right .yui-nav .selected { + margin:0 0 0.16em -1px; +} + +.yui-skin-sam .yui-navset-left .yui-nav a, +.yui-skin-sam .yui-navset-right .yui-nav a { + border-width:1px 0; +} + +.yui-skin-sam .yui-navset-left .yui-nav a em, +.yui-skin-sam .yui-navset .yui-navset-left .yui-nav a em, +.yui-skin-sam .yui-navset-right .yui-nav a em { + border-width:0 0 0 1px; + padding:0.2em .75em; + top:auto; + left:-1px; /* for 1px rounded corners */ +} + +.yui-skin-sam .yui-navset-right .yui-nav a em { + border-width:0 1px 0 0; + left:auto; + right:-1px; /* for 1px rounded corners */ +} + +.yui-skin-sam .yui-navset-left .yui-nav a, +.yui-skin-sam .yui-navset-left .yui-nav .selected a, +.yui-skin-sam .yui-navset-left .yui-nav a:hover, +.yui-skin-sam .yui-navset-right .yui-nav a, +.yui-skin-sam .yui-navset-right .yui-nav .selected a, +.yui-skin-sam .yui-navset-right .yui-nav a:hover, +.yui-skin-sam .yui-navset-bottom .yui-nav a, +.yui-skin-sam .yui-navset-bottom .yui-nav .selected a, +.yui-skin-sam .yui-navset-bottom .yui-nav a:hover { + background-image:none; /* no left-right or bottom-top gradient */ +} + +.yui-skin-sam .yui-navset-left .yui-content { + border:1px solid #eef2fd; /* content border */ +} + +/* bottom orientation */ +.yui-skin-sam .yui-navset-bottom .yui-nav, +.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav { + border-width:5px 0 0; /* color between tab list and content */ +} + +.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav .selected, +.yui-skin-sam .yui-navset-bottom .yui-nav .selected { + margin:-1px 0.3em 0 0; /* for overlap */ +} + +.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav li, +.yui-skin-sam .yui-navset-bottom .yui-nav li { + padding:0 0 1px 0; /* gecko: make room for overflow */ + vertical-align:top; +} + +.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav li a, +.yui-skin-sam .yui-navset-bottom .yui-nav li a { +} + +.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav a em, +.yui-skin-sam .yui-navset-bottom .yui-nav a em { + border-width:0 0 1px; + top:auto; + bottom:-1px; /* for 1px rounded corners */ +} + +.yui-skin-sam .yui-navset-bottom .yui-content, +.yui-skin-sam .yui-navset .yui-navset-bottom .yui-content { + border:1px solid #eef2fd; /* content border */ +} + + +.yui-skin-sam { + background-color: #ffa700; + padding: 10px 5 5 5px; + display:block; +} + +/* +Copyright (c) 2008, Yahoo! Inc. All rights reserved. +Code licensed under the BSD License: +http://developer.yahoo.net/yui/license.txt +version: 2.6.0 +*/ +.yui-navset .yui-nav li,.yui-navset .yui-navset-top .yui-nav li,.yui-navset .yui-navset-bottom .yui-nav li{margin:0 0.5em 0 0;} + +.yui-navset-left .yui-nav li,.yui-navset-right .yui-nav li{margin:0 0 0.5em;} + +.yui-navset .yui-content .yui-hidden{display:none;} + +.yui-navset .yui-navset-left .yui-nav,.yui-navset .yui-navset-right .yui-nav,.yui-navset-left .yui-nav,.yui-navset-right .yui-nav{width:6em;} + +.yui-navset-top .yui-nav,.yui-navset-bottom .yui-nav{width:auto;}.yui-navset .yui-navset-left,.yui-navset-left{padding:0 0 0 6em;} + +.yui-navset-right {padding:0 6em 0 0;} + +.yui-navset-top,.yui-navset-bottom{padding:auto;} + +.yui-nav,.yui-nav li{margin:0;padding:0;list-style:none;} + +.yui-navset li em{font-style:normal;}.yui-navset{position:relative;zoom:1;} + +.yui-navset .yui-content{zoom:1;} + +.yui-navset .yui-nav li,.yui-navset .yui-navset-top .yui-nav li,.yui-navset .yui-navset-bottom .yui-nav li{display:inline-block;display:-moz-inline-stack;*display:inline;vertical-align:bottom;cursor:pointer;zoom:1;} + +.yui-navset-left .yui-nav li,.yui-navset-right .yui-nav li{display:block;} + +.yui-navset .yui-nav a{position:relative;} + +.yui-navset .yui-nav li a,.yui-navset-top .yui-nav li a,.yui-navset-bottom .yui-nav li a{display:block;display:inline-block;vertical-align:bottom;zoom:1;} + +.yui-navset-left .yui-nav li a,.yui-navset-right .yui-nav li a{display:block;} + +.yui-navset-bottom .yui-nav li a{vertical-align:text-top;} + +.yui-navset .yui-nav li a em,.yui-navset-top .yui-nav li a em,.yui-navset-bottom .yui-nav li a em{display:block;} + +.yui-navset .yui-navset-left .yui-nav,.yui-navset .yui-navset-right .yui-nav,.yui-navset-left .yui-nav,.yui-navset-right .yui-nav{position:absolute;z-index:1;} + +.yui-navset-top .yui-nav,.yui-navset-bottom .yui-nav{position:static;} + +.yui-navset .yui-navset-left .yui-nav,.yui-navset-left .yui-nav{left:0;right:auto;} + +.yui-navset .yui-navset-right .yui-nav,.yui-navset-right .yui-nav{right:0;left:auto;} + +.yui-skin-sam .yui-navset .yui-nav .selected a em{padding:0.35em 0.75em;} + +.yui-skin-sam .yui-navset-left .yui-nav,.yui-skin-sam .yui-navset .yui-navset-left .yui-nav,.yui-skin-sam .yui-navset .yui-navset-right .yui-nav,.yui-skin-sam .yui-navset-right .yui-nav{border-width:0 5px 0 0;Xposition:absolute;top:0;bottom:0;} + +.yui-skin-sam .yui-navset .yui-navset-right .yui-nav,.yui-skin-sam .yui-navset-right .yui-nav{border-width:0 0 0 5px;} + +.yui-skin-sam .yui-navset-left .yui-nav li,.yui-skin-sam .yui-navset .yui-navset-left .yui-nav li,.yui-skin-sam .yui-navset-right .yui-nav li{margin:0 0 0.16em;padding:0 0 0 1px;} + +.yui-skin-sam .yui-navset-right .yui-nav li{padding:0 1px 0 0;} + +.yui-skin-sam .yui-navset-left .yui-nav a,.yui-skin-sam .yui-navset-right .yui-nav a{border-width:1px 0;} + +.yui-skin-sam .yui-navset-left .yui-nav a em,.yui-skin-sam .yui-navset .yui-navset-left .yui-nav a em,.yui-skin-sam .yui-navset-right .yui-nav a em{border-width:0 0 0 1px;padding:0.2em .75em;top:auto;left:-1px;} + +.yui-skin-sam .yui-navset-right .yui-nav a em{border-width:0 1px 0 0;left:auto;right:-1px;} + +.yui-skin-sam .yui-navset-left .yui-nav a,.yui-skin-sam .yui-navset-left .yui-nav .selected a,.yui-skin-sam .yui-navset-left .yui-nav a:hover,.yui-skin-sam .yui-navset-right .yui-nav a,.yui-skin-sam .yui-navset-right .yui-nav .selected a,.yui-skin-sam .yui-navset-right .yui-nav a:hover,.yui-skin-sam .yui-navset-bottom .yui-nav a,.yui-skin-sam .yui-navset-bottom .yui-nav .selected a,.yui-skin-sam .yui-navset-bottom .yui-nav a:hover{background-image:none;} + +.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav .selected,.yui-skin-sam .yui-navset-bottom .yui-nav .selected{margin:-1px 0.16em 0 0;} + +.yui-skin-sam .yui-navset .yui-navset-bottom .yui-nav li,.yui-skin-sam .yui-navset-bottom .yui-nav li{padding:0 0 1px 0;vertical-align:top;} + + diff --git a/www/extras/account/images/new.png b/www/extras/account/images/new.png new file mode 100644 index 000000000..45d7f0676 Binary files /dev/null and b/www/extras/account/images/new.png differ diff --git a/www/extras/account/images/next.gif b/www/extras/account/images/next.gif new file mode 100644 index 000000000..d00933441 Binary files /dev/null and b/www/extras/account/images/next.gif differ diff --git a/www/extras/account/images/no_photo.gif b/www/extras/account/images/no_photo.gif new file mode 100644 index 000000000..cd34a822f Binary files /dev/null and b/www/extras/account/images/no_photo.gif differ diff --git a/www/extras/account/images/old.png b/www/extras/account/images/old.png new file mode 100644 index 000000000..e43f504ce Binary files /dev/null and b/www/extras/account/images/old.png differ diff --git a/www/extras/account/images/prev.gif b/www/extras/account/images/prev.gif new file mode 100644 index 000000000..47ccf43bb Binary files /dev/null and b/www/extras/account/images/prev.gif differ diff --git a/www/extras/account/images/save_changes.gif b/www/extras/account/images/save_changes.gif new file mode 100644 index 000000000..897b100d4 Binary files /dev/null and b/www/extras/account/images/save_changes.gif differ diff --git a/www/extras/account/inbox.js b/www/extras/account/inbox.js new file mode 100644 index 000000000..16823857a --- /dev/null +++ b/www/extras/account/inbox.js @@ -0,0 +1,64 @@ +YAHOO.util.Event.onDOMReady(function() { + if(YAHOO.util.Dom.inDocument("friends")) { + + var isUserCheckBox = function ( element ) { + if(element.name == "friend") return true; + return false; + } + + var removeUser = function (evt, obj) { + YAHOO.util.Event.stopEvent(evt); + var userId = obj.userId; + var checkBox = YAHOO.util.Dom.get("friend_"+userId+"_id"); + checkBox.checked = false; + updateUsers(evt,obj.dialog); + } + + var updateUsers = function ( evt , dialog ) { + YAHOO.util.Event.stopEvent(evt); + var toElement = YAHOO.util.Dom.get("messageTo"); + toElement.innerHTML = ""; // Clear the current stuff + YAHOO.util.Dom.removeClass(toElement,"inbox_messageTo"); + + var checkBoxes = YAHOO.util.Dom.getElementsBy(isUserCheckBox,"INPUT","contacts"); + for (var i = 0; i < checkBoxes.length; i++) { + if(checkBoxes[i].checked) { + var friendName = YAHOO.util.Dom.get("friend_"+checkBoxes[i].value+"_name").innerHTML; + var firstPart = document.createTextNode(friendName + " ( "); + var link = document.createElement("A"); + link.setAttribute('href', '#'); + link.innerHTML = removeText; + YAHOO.util.Event.addListener(link,"click",removeUser,{ userId: checkBoxes[i].value, dialog: dialog }); + var lastPart = document.createTextNode(" ); "); + toElement.appendChild(firstPart); + toElement.appendChild(link); + toElement.appendChild(lastPart); + } + } + YAHOO.util.Dom.addClass(toElement,"inbox_messageTo"); + dialog.hide(); + } + + var showUsers = function (evt, dialog) { + YAHOO.util.Event.stopEvent(evt); + dialog.show(); + } + + // Instantiate the Dialog + var dialog1 = new YAHOO.widget.Dialog("friends", { + width : "340px", + fixedcenter : true, + visible : false, + constraintoviewport : false + }); + + // Render the Dialog + dialog1.render(); + + YAHOO.util.Event.addListener("show_friends", "click", showUsers, dialog1); + YAHOO.util.Event.addListener("cancel_top", "click", dialog1.hide, dialog1, true); + YAHOO.util.Event.addListener("cancel_bottom", "click", dialog1.hide, dialog1, true); + YAHOO.util.Event.addListener("update_top", "click", updateUsers, dialog1); + YAHOO.util.Event.addListener("update_bottom", "click", updateUsers, dialog1); + } +}); \ No newline at end of file