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