webgui/lib/WebGUI/Account/Profile.pm

588 lines
21 KiB
Perl

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 appendCategoryVars ( var, category [,fields, errors] )
Appends cateogry variables to the hash ref passed in
=head3 var
The hash reference to append template variables to
=head3 category
WebGUI::ProfileCategory object to append variables for
=head3 fields
Optional array ref of fields in this category
=head3 errors
Optional array ref of errors to attach to the category loop
=cut
sub appendCategoryVars {
my $self = shift;
my $var = shift || {};
my $category = shift;
my $fields = shift;
my $errors = shift;
my $selected = $self->store->{selected} || $self->session->form->get("selected");
my $categoryId = $category->getId;
my $categoryLabel = $category->getLabel;
my $shortCategoryLabel = $category->getShortLabel;
my $isActive = $categoryId eq $selected;
my $index = scalar(@{$var->{'profile_category_loop'}}) + 1;
push(@{ $var->{'profile_category_loop'} }, {
'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' => $index,
'profile_fields_loop' => $fields,
'profile_errors' => $errors,
});
$var->{'profile_category_'.$categoryId."_isActive" } = $isActive;
$var->{'profile_category_'.$categoryId."_label" } = $categoryLabel;
$var->{'profile_category_'.$categoryId."_shortLabel"} = $shortCategoryLabel;
$var->{'profile_category_'.$categoryId."_index" } = $index;
$var->{'profile_category_'.$categoryId."_fields" } = $fields;
$var->{'can_edit_profile' } = $self->uid eq $self->session->user->userId;
#Update the isActive flag to determine the default active tab
$self->store->{hasActiveTab} = ($self->store->{hasActiveTab} || $isActive);
#return $index;
}
#-------------------------------------------------------------------
=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 = $self->getUser;
my $pageUrl = $session->url->page;
$self->SUPER::appendCommonVars($var);
$var->{'edit_profile_url' } = $self->getUrl("module=profile;do=edit");
$var->{'invitations_enabled' } = $user->profileField('ableToBeFriend');
$var->{'profile_category_loop'} = [];
#Append the categories
my $categories = WebGUI::ProfileCategory->getCategories($session, { editable=>1 } );
map { $self->appendCategoryVars($var,$_) } @ { $categories };
unless ($self->store->{hasActiveTab}) {
$var->{'profile_category_loop'}->[0]->{'profile_category_isActive'} = 1;
}
#Append the form submit if it's in edit mode
if($self->method eq "edit" || $self->uid eq "") {
$var->{'is_edit' } = "true";
$var->{'form_header' } = WebGUI::Form::formHeader($session,{
action => $self->getUrl("module=profile;do=editSave")
});
$var->{'form_footer' } = WebGUI::Form::formFooter($session);
}
}
#-------------------------------------------------------------------
=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 => "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("profileViewTemplateId", $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 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;
return $self->session->setting->get("profileLayoutTemplateId") || "FJbUTvZ2nUTn65LpW6gjsA";
}
#-------------------------------------------------------------------
=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 $var = {};
#Handle errors
my @errorFields = ();
$var->{'profile_errors'} = [];
if( scalar(keys %{$errors}) ) {
#Warnings and errors are the same here - set the fields so we can tell which fields errored
@errorFields = (@{$errors->{errorFields}},@{$errors->{warningFields}});
#Build the error message loop
map {
push( @{$var->{'profile_errors'}},{ error_message => $_ })
} @{$errors->{errors}};
}
my $count = 0;
#Set the active flag to the default. We'll know more later
$self->store->{hasActiveTab} = 0;
#Initialize the category template loop which gets filled inside the loop
$var->{'profile_category_loop'} = [];
#Cache the privacy settings
my $privacySettingsHash = WebGUI::ProfileField->getPrivacyOptions($session);
#Get the editable categories
my $categories = WebGUI::ProfileCategory->getCategories($session, { editable => 1 } );
foreach my $category (@{ $categories } ) {
my @fields = ();
foreach my $field (@{ $category->getFields( { editable => 1 } ) }) {
my $fieldId = $field->getId;
my $fieldLabel = $field->getLabel;
my $fieldForm = $field->formField({ extras=>$self->getExtrasStyle($field,\@errorFields,$user->profileField($fieldId)) });
my $fieldRequired = $field->isRequired;
my $fieldExtras = $field->getExtras;
my $fieldViewable = $field->isViewable;
my $rawPrivacySetting = $user->getProfileFieldPrivacySetting($fieldId);
my $fieldPrivacySetting = $privacySettingsHash->{$rawPrivacySetting};
my $fieldPrivacy = WebGUI::Form::selectBox($session,{
name => "privacy_$fieldId",
options => $privacySettingsHash,
value => $rawPrivacySetting,
extras => (!$fieldViewable) ? " disabled" : ""
});
#Create a seperate template var for each field
my $fieldBase = 'profile_field_'.$fieldId;
$var->{$fieldBase.'_form' } = $fieldForm;
$var->{$fieldBase.'_label' } = $fieldLabel;
$var->{$fieldBase.'_required' } = $fieldRequired;
$var->{$fieldBase.'_extras' } = $fieldExtras;
$var->{$fieldBase.'_privacy_form' } = $fieldPrivacy;
$var->{$fieldBase.'_field_viewable' } = $fieldViewable;
$var->{$fieldBase.'_privacy_setting' } = $fieldPrivacySetting;
$var->{$fieldBase.'_privacy_is_'.$rawPrivacySetting } = $rawPrivacySetting;
push(@fields, {
'profile_field_id' => $fieldId,
'profile_field_form' => $fieldForm,
'profile_field_label' => $fieldLabel,
'profile_field_required' => $fieldRequired,
'profile_field_extras' => $fieldExtras,
'profile_field_viewable' => $fieldViewable,
'profile_field_privacy_form' => $fieldPrivacy,
'profile_field_privacy_setting' => $fieldPrivacySetting,
'profile_field_privacy_is_'.$rawPrivacySetting => $rawPrivacySetting,
});
}
#Append the category variables
$self->appendCategoryVars($var,$category,\@fields,$var->{'profile_errors'});
}
#If not category is selected, set the first category as the active one
unless ($self->store->{hasActiveTab}) {
$var->{'profile_category_loop'}->[0]->{'profile_category_isActive'} = 1;
}
#Call the superclass common vars method cause we don't need to build the categories again
$self->SUPER::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}})) {
my $profile = $retHash->{profile};
my $privacy = {};
$session->user->update($profile);
my $address = {};
my $address_mappings = WebGUI::Shop::AddressBook->getProfileAddressMappings;
foreach my $fieldName (keys %{$profile}) {
#set the shop address fields
my $address_key = $address_mappings->{$fieldName};
$address->{$address_key} = $profile->{ $fieldName } if ($address_key);
#set the privacy settings
my $privacySetting = $session->form->get("privacy_".$fieldName);
next unless $privacySetting;
$privacy->{$fieldName} = $privacySetting;
}
$session->user->setProfileFieldPrivacySetting($privacy);
#Update or create and update the shop address
if ( keys %$address ) {
$address->{'isProfile' } = 1;
#Get the address book for the user (one is created if it does not exist)
my $addressBook = WebGUI::Shop::AddressBook->newByUserId($session,$self->uid);
my $profileAddress = eval { $addressBook->getProfileAddress() };
my $e;
if($e = WebGUI::Error->caught('WebGUI::Error::ObjectNotFound')) {
#Get home address only mappings to avoid creating addresses with just firstName, lastName, email
my %home_address_map = %{$address_mappings};
foreach my $exclude ( qw{ firstName lastName email } ) {
delete $home_address_map{$exclude};
}
#Add the profile address for the user if there are homeAddress fields
if( grep { $address->{$_} } values %home_address_map ) {
$address->{label} = "Profile Address";
my $new_address = $addressBook->addAddress($address);
#Set this as the default address if one doesn't already exist
my $defaultAddress = eval{ $addressBook->getDefaultAddress };
if(WebGUI::Error->caught('WebGUI::Error::ObjectNotFound')) {
$addressBook->update( {
defaultAddressId => $new_address->getId
} );
}
}
}
elsif ($e = WebGUI::Error->caught) {
#Bad stuff happened - log an error but don't fail since this isn't a vital function
$session->log->error(
q{Could not update Shop Profile Address for user }
.$self->username.q{ : }.$e->error
);
}
else {
#Update the profile address for the user
$profileAddress->update($address);
}
}
}
#Store the category the error occurred in the object for reference
$self->store->{selected} = $retHash->{errorCategory};
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);
my $privacySetting = $user->profileField('publicProfile') || 'none';
$var->{"profile_privacy_$privacySetting"} = "true";
$var->{'acceptsPrivateMessages'}
= $user->acceptsPrivateMessages($session->user->userId);
$var->{'acceptsFriendsRequests'}
= $user->acceptsFriendsRequests($session->user);
#Check user privileges
unless ($user->profileIsViewable($session->user)) {
my $i18n = WebGUI::International->new($session,'Account_Profile');
$var->{'notViewable'} = 1;
$var->{'error_message'} = $i18n->get("profile not public error");
return $self->processTemplate($var,$self->getViewTemplateId);
}
#Cache the privacy settings
my $privacySettingsHash = WebGUI::ProfileField->getPrivacyOptions($session);
$var->{'profile_category_loop' } = [];
foreach my $category (@{WebGUI::ProfileCategory->getCategories($session,{ visible => 1})}) {
my @fields = ();
foreach my $field (@{$category->getFields({ visible => 1 })}) {
next unless ($user->canViewField($field->getId,$session->user));
my $rawPrivacySetting = $user->getProfileFieldPrivacySetting($field->getId);
my $privacySetting = $privacySettingsHash->{$rawPrivacySetting};
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
my $fieldBase = 'profile_field_'.$fieldId;
$var->{$fieldBase.'_label' } = $fieldLabel;
$var->{$fieldBase.'_value' } = $fieldValue;
$var->{$fieldBase.'_raw' } = $fieldRaw;
$var->{$fieldBase.'_privacySetting' } = $privacySetting;
$var->{$fieldBase.'_privacy_is_'.$rawPrivacySetting } = "true";
push(@fields, {
'profile_field_id' => $fieldId,
'profile_field_is_'.$fieldId => "true",
'profile_field_label' => $fieldLabel,
'profile_field_value' => $fieldValue,
'profile_field_raw' => $fieldRaw,
'profile_field_privacySetting' => $privacySetting,
'profile_field_privacy_is_'.$rawPrivacySetting => "true",
});
}
#Don't bother displaying the category if there's nothing in it.
next unless (scalar(@fields));
#Append the category variables
$self->appendCategoryVars($var,$category,\@fields);
}
#If not category is selected, set the first category as the active one
unless ($self->store->{hasActiveTab}) {
$var->{'profile_category_loop'}->[0]->{'profile_category_isActive'} = 1;
}
return $self->processTemplate($var,$self->getViewTemplateId);
}
1;