update user


Uploading users data would be done partially. All other data can be changed from the same form but we need to create a different form for the password section. So let's go with the first or the easier one.

USERS DATA UPDATE

Let's have a look at the user data update form. Since we are creating two forms in the same page, we can't generate csrf_token twice as that'll make the first token void instantly. Instead, we'll hold that single value in one variable and send that value via both forms.

<?php 
$id = session::get('authenticated_userid');
$obj = new User();	
$user = $obj->getUser($id);
$token = token::input();

if (Request::method() && token::check(Request::post('csrf_token'))){
	
	if(isset($_POST['update_info'])){
		$obj -> updateUserInfo();
	}	
}
?>

<div class="col-sm-12">
	<div class="row">
		<div class="col-sm-6">
			<div class="col-sm-12">
				<?= Validation::displayErrors('validationErrors'); ?>
				<?= Message(); ?>
			</div>	
			<form method="POST" enctype="multipart/form-data">
				<h2>Update User Info</h2>				
				<?=$token?>
				<div class="form-group">							
					<input type="hidden" name="id" value="<?=$user->id?>">
					<label>Username</label>
					<input type="text" name="username" value="<?=$user->username?>" class="form-control">
				</div>
				<div class="form-group">
					<label>Email</label>
					<input type="email" name="email" value="<?=$user->email?>" class="form-control">
				</div>				
				<div class="form-group">
					<label>Profile Picture</label>
					<input type="file" name="uploads" class="btn btn-default">
				</div>
				<div class="form-group">
					<button type="submit" name="update_info" class="btn btn-success"><i class="fa fa-user-plus"></i> Update Info</button>
				</div>
			</form>
		</div>

		<div class="col-sm-6">
			<img src="<?=HTTP.'admin/Upload/Users/' . $user->uploads?>">
		</div>
	</div>
</div>		

As it's a user information update page, we need to display the user data in form fields from where the user can change his informations as per his need. We could have done it via get method by sending the userid via url but this one will be much secured as no one can change other's informations.

We retrieve the userid of the active user via session as it'll be stored in the session after a user is logged in and instantiate the user controller class and call for the getUser() function that retrieves the user data by id.

Then, we displayed all the general informations i.e. username, email and profile picture of the user in that page. The usertype and user status will be handled by administrator only who can control the user access to the application.

We gave a distinct name to the submit button to call related function upon submit. In this case, the submit button will instantiate the updateUserInfo() function in user controller. Let's create that function and update all the informations.

public function updateUserInfo(){

	$data['username'] = Request::post('username');
	$data['email'] = Request::post('email');
	$id = (int)Request::post('id');

	try{
		$this->validationRules['email']['unique'] = "users.email.id.".$id;
		$this->_validation->validate($this->validationRules);
			
		if($this->_validation->isValid()){
				
			if(!empty($_FILES['uploads']['name'])){
					
				$configs['upload_size'] = 2000000;
				$configs['upload_ext'] = 'jpg|jpeg|png|gif';
				$configs['upload_path'] = ROOT.'admin/Upload/Users/';
				Upload::initialize($configs);
				$filename = Upload::load($_FILES['uploads']);
							
				if($filename && $this->deleteAssociate($id)){

					$data['uploads'] = $filename;
					session::delete('authenticated_image');
					session::put('authenticated_image',$filename);

				}else{

					session::put('validationErrors',Upload::getErrors());
					return Redirect::to('admin/profile/');
				}
			}

			if($this->save($data,$id)){
				session::put('success','User information updated successfully');
				return Redirect::to('admin/profile/');
			}	

		}else{
			session::put('validationErrors',$this->_validation->getErrors());
			return Redirect::to('admin/profile/');
		}		
	}catch(Exception $e){
		die($e->getMessage());
	}
}

First, we'll hold the username and email value in array and store the user id in another variable as wee need it for update SQL.

We sent the validation rule and rule values for unique email case that we discussed earlier. This way, our application script will exclude the active user's id while hecking for the unique case which means same email value can be added by him but not the ones that matches other email entries.

Then we go to the image validation process only in the case the user opted to change it. If a new image is uploaded the image in session also needs to be replaced. That's exactly what we did after image upload.

if the user attempted to change his profile picture but couldn't succeed due to validation issues, same errors will be displayed while redirecting the user back to the same page. Else, the success message will be displayed to the user. In case of username or email validation errors, same would be displayed to the user.

UPDATE PASSWORD

While sending data from this form, we'll update our request check codes too as follows.

if (Request::method() && token::check(Request::post('csrf_token'))){
	if(isset($_POST['update_info'])){
		$obj -> updateUserInfo();
	}
	if(isset($_POST['update_password'])){
		$obj -> updatePassword();
	}
}	

If the request is sent via button named update_password, then the data processing function would be updatePassword(). Let's have a look at the form before creating that function.

<form method="post">
	<div class="col-sm-12">
		<h2><i class="fa fa-lock"></i> Change Password</h2>
	</div>	
	<?=$token?>
	<input type="hidden" name="id" value="<?=$user->id?>">
	<div class="col-sm-4 form-group">
		<label>Old Password</label>
		<input type="password" name="oldpassword" class="form-control">
	</div>
	<div class="col-sm-4 form-group">
		<label>New Password</label>
		<input type="password" name="password" class="form-control">
	</div>
	<div class="col-sm-4 form-group">
		<label>Confirm Password</label>
		<input type="password" name="cpassword" class="form-control">
	</div>	
	<div class="col-sm-12 form-group">
		<button type="submit" name="update_password" class="btn btn-success"><i class="fa fa-user-plus"></i> Change Password</button>
	</div>		
</form>	

We sent the csrf_token value along with the userid via this form too. We'll ask the user to input previous password while changing the password for security confirmation. Then, there's the field for new password and new password confirmation. Once, the form is submitted, we'll need updatePassword() function to process further. Let's have a look at that function now.

public function updatePassword(){
	
	$old = Request::post('oldpassword');
	$id = Request::post('id');
	$user = $this->getUser($id);
	
	try{	
		if(empty($user)) throw new Exception("User Not Found");
		$oldpassword = $user->password;
		
		if(hash::decrypt($oldpassword,$old)){
				
			$data['password'] = hash::make(Request::post('password'));
			$this->_validation->validate($this->validationRules);
				
			if($this->_validation->isValid()){
		
				if($this->save($data,$id)){
					session::put('success','Password Updated');
					return Redirect::to('admin/profile/');
				}
			}else{
				session::put('validationErrors',$this->_validation->getErrors());
				return Redirect::to('admin/profile/');
			}				
		}else{
			session::put('error','Old Password did not match');
			return Redirect::to('admin/profile/');
		} 
	}catch(Exception $e){
		die($e->getMessage);
	}	
}	

First, we'll store old password and user id sent from the post in variables and retrieve the user by that id. If there's any user with that id in the table we'll process further else we'll redirect back.

The old password sent form the post will be verified using the password from database and the error will be displayed using session in case of error.

If the password matches and new password value matches the confirm new password value, the password will be updated and success message will be displayed to the user. In case of validation error, same will be displayed to the user and redirected back.