package WebGUI::Macro::updateProfile; #------------------------------------------------------------------- # WebGUI is Copyright 2001-2005 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 macro is Copyright 2007 United Knowledge # http://www.unitedknowledge.nl/ # Author: Arjan Widlak # Version: 0.1 # Date: 28th of August 2007 # Licence: GPL http://www.gnu.org/licenses/gpl-2.0.html #------------------------------------------------------------------- use strict; use WebGUI::Macro; use WebGUI::User; use WebGUI::Form; use WebGUI::Storage; use WebGUI::Storage::Image; #------------------------------------------------------------------- sub my_validateProfileData { my $session = shift; my @updatedFields = @_; my %data = (); my $error = ""; my $warning = ""; my $i18n = WebGUI::International->new($session); ## Niet voor elk profielveld, maar voor die in het formulier: ## Hier kunnen velden tussen zitten die niet bekend zijn in het profiel #foreach my $field (@{WebGUI::ProfileField->getEditableFields($session)}) { my $matchResult; my $params = $session->form->paramsHashRef; foreach my $fieldInProfile (@{WebGUI::ProfileField->getEditableFields($session)}) { my $profileFieldName = $fieldInProfile->getId; foreach my $fieldReceived (keys %{$params}) { ## All fields that are already updated should be skipped # The greatest risk is avatar and file fields being updated with old values # But if it's updated it's in updatedFields # However if updatedFields is empty it will always match # so, we only skip if it's not empty my $values = "@updatedFields"; #$matchResult .= "fieldReceived match and not empty don't process, next
" if (($fieldReceived =~ $values) && ($values ne "")); #$matchResult .= "values is empty: $values
" if $values eq ""; #$matchResult .= "field does not match: $fieldReceived, $values
"; #$matchResult .= "fields are equal: $fieldReceived, $profileFieldName
" if $profileFieldName eq $fieldReceived; ## Exclude if already updated next if (($fieldReceived =~ $values) && ($values ne "")); ## Exclude everything that's not received. next unless $fieldReceived eq $profileFieldName; ## Exclude the normal File and Image fields my $fieldType = $fieldInProfile->get("fieldType"); next if (($fieldType eq "Image") or ($fieldType eq "File")); ## Start the real work my $fieldValue = $fieldInProfile->formProcess; if (ref $fieldValue eq "ARRAY") { $data{$fieldInProfile->getId} = $$fieldValue[0]; } else { $data{$fieldInProfile->getId} = $fieldValue; } if ($fieldInProfile->isRequired && $data{$fieldInProfile->getId} eq "") { $error .= '
  • '.$fieldInProfile->getLabel.' '.$i18n->get(451).'
  • '; } elsif ($fieldInProfile->getId eq "email" && WebGUI::Operation::Profile::isDuplicateEmail($session,$data{$fieldInProfile->getId})) { $warning .= '
  • '.$i18n->get(1072).'
  • '; } if ($fieldInProfile->getId eq "language" && $fieldValue ne "") { unless (exists $i18n->getLanguages()->{$fieldValue}) { $error .= '
  • '.$fieldReceived->getLabel.' '.$i18n->get(451).'
  • '; } } } } #return $matchResult; return (\%data, $error, $warning); } #-------:------------------------------------------------------------ sub process { my $session = shift; my $newLocation = shift; my $confirmMessage = shift; #my $userId = WebGUI::Form::Hidden->new($session,{name => 'userId'})->getValueFromPost; my $user = WebGUI::User->new($session,$session->user->userId); my $userId = $session->user->userId; return if $userId eq '1'; my $messages; #errors display them if there are messages. my $fieldsUpdated = 0; #only go to the new location if fields are updated. ## # I would like to upload a new file/photo immediately, not first delete it and later return # so I'm going to write my own sub getValueFromPost, that can do that # first I'm going to loop through alle editable profilefields to look for fields of type File/Image # those will be processed first by my_getValueFromPost # I do not use validateProfileData on these files - data is not validated - because validateProfileFields # calls formProcess and actually uploads the files without returning the id. Perhaps this id can be retrieved # but that's something for another time. # # while we're in the loop, if not type File/Image, we might as well do the other thing: validateProfileData # I wrote my own sub validateProfileData, because the original forces you to present all required fields. # # ## Have the received name/value pairs accessible: my $params = $session->form->paramsHashRef; my @namesReceived = keys %{$params}; ## Record updated file/images fields my @updatedFiles; my $received; ## loop throught all editable profile fields foreach my $fieldInProfile (@{WebGUI::ProfileField->getEditableFields($session)}) { ## Here getId gives the Name of the profileField in the database my $fieldName = $fieldInProfile->getId; my $valueReceived = $params->{$fieldName."_file"}; ## If no value is received, we leave the field for what it is. # Only if a new value is received, we act if ($valueReceived) { ## is this one of the file/image type? # It should be, cause we added _file to the fieldName my $fieldType = $fieldInProfile->get("fieldType"); if (($fieldType eq "Image") or ($fieldType eq "File")) { $received .= $valueReceived ." in files
    "; ## Record this field of type File/Image is updated push @updatedFiles,$fieldName; ## Get the storageId of the old one if it exists # Note: the new file is given with a name that ends on _file # the old value has the same name without file # fieldName comes from the database and does not have the _file my $storageId = $params->{$fieldName}; my $storage; if ($storageId) { ## Delete it $storage = WebGUI::Storage::Image->get($session,$storageId) if $fieldType eq "Image"; $storage = WebGUI::Storage::File->get($session,$storageId) if $fieldType eq "File"; $storage->delete(); } else { #$storage = WebGUI::Storage->create($session); # if a new storage location is created, get it's Id #$storageId = $storage->getId; } ## In alle cases: create a new storage location my $newStorage; $newStorage = WebGUI::Storage::Image->create($session,$storageId) if $fieldType eq "Image"; $newStorage = WebGUI::Storage::File->create($session,$storageId) if $fieldType eq "File"; ## upload the new one $newStorage->addFileFromFormPost($fieldName."_file",1000); my @files = @{ $newStorage->getFiles }; if (scalar(@files) < 1) { $newStorage->delete; $messages .= "Error: $fieldName niet goed ontvangen. Bestand te groot?
    "; } else { ## get the new StorageId my $newStorageId = $newStorage->getId; ## If it's an image, generate a thumbnail my $file = $newStorage->getFiles->[0] if $fieldType eq "Image"; my $success = $newStorage->generateThumbnail($file) if $fieldType eq "Image"; ## update the users profile $user->profileField($fieldName,$newStorageId); $fieldsUpdated++; } } } } ## Files that are not updated, but kept, should be updated: foreach my $fieldReceived (keys %{$params}) { ## We can encounter three types of input files, the name, the name ending on _file and _action # we only pay attention to _file, if this one does *not* match with updatedFiles, then # we update that field. my $updatedNames = "@updatedFiles"; if ($updatedNames eq "" && $fieldReceived =~ /_file$/ ) { ## updatedNames is empty, it will always match, update all realNames my $realName = $fieldReceived; $realName =~ s/_file$//; $user->profileField($realName,$params->{$realName}); }else{ if (($fieldReceived) =~ /_file$/ && !($fieldReceived =~ $updatedNames)) { my $realName = $fieldReceived; $realName =~ s/_file$//; $user->profileField($realName,$params->{$realName}); } } } ## We now have all file-type files in my @updatedFiles # They are uploaded and updated in the profile # We are going to pass this array to my_validateProfileData, so it can be excluded there my ($profile, $fieldName, $error, $u, $warning); ($profile, $error, $warning) = my_validateProfileData($session, @updatedFiles); $messages .= $error; $messages .= $warning; my $match; foreach my $field ( keys %{$profile} ) { # In this loop are only the fields that need to be updated # all others are excluded in my_validateProfileData that builds $profile $user->profileField($field,$profile->{$field}); $fieldsUpdated++; } ## Where do we go? # If not ok, go to the current location, display messages return $messages if $messages; # If ok, go to the new location return ($session->http->setRedirect($newLocation),"$confirmMessage") if $fieldsUpdated > 0; return; } 1;