<?php	
/**
 * Customer Password Controller class
 * 
 * @author neilcorke <neil@corkeweb.com>
 *
 */
class Customer_PasswordController extends Zend_Controller_Action
{
     /**
     * Action to reset lost customer password
     * 
     * @access public
     */
    public function lostAction()
    {
    	$form = new Customer_Form_LostPasswordForm();
		$this->view->form = $form;
		
    	// Add success messages to view:
    	if ($this->_helper->getHelper('FlashMessenger')->getMessages()) {
      		
  			$this->view->messages = $this->_helper->getHelper('FlashMessenger')->getMessages(); 
    	}
			
    	// If valid input:
    	if ($this->_request->isPost() && $form->isValid($_POST)) {
    			
    		// Email address provided
    		$emailAddress = $form->getValue('email');
    			
    		// Retrieve customer ID:
    		$customerService = new Falk_CustomerService();
			$customerId = (int) $customerService->GetCustomerIdByEmail($emailAddress);

			// If customer ID valid:
			if ($customerId > 0) {
					
				// Create UUID key:
				$key = Falk_Utility_Uuid::generate();
	
				// Save password reset data:
				$passwordResetService = new Falk_PasswordResetService();
				$passwordResetService->NewPasswordReset($customerId, $key);
				
				// Reset URL:
				$resetURL = $this->_helper->link->passwordReset($key);
				
				// Saluation by customer preference:
				$name = $customerService->getCustomerSalutation($customerId);
				
				// Sender info from local config.ini
    			$configs = $this->getInvokeArg('bootstrap')->getOption('configs');
	  			$localConfig = new Zend_Config_Ini($configs['localConfigPath']);
				
				// Generate activation email to customer:
				$email = new Falk_Mailer_Html($localConfig->email->customerservice);
				$email->setSubject('Falk Culinair Password Reset Service')
			  	      ->addTo($emailAddress, $name)
			  	      ->setEmailParam('name', $name)
			  	      ->setEmailParam('url', $resetURL)
			  	      ->setEmailParam('customerService', $this->_helper->link->customerService())
			  		  ->sendTemplate('password-reset');
			  
			  	// Set success message:
    		  	$this->_helper->getHelper('FlashMessenger')->addMessage('Success');
    		
    			// Redirect back to address book:
    			$this->_redirect('/customer/password/lost/success');
					
			} else {
				
				// Email address not registered:
				$error = 'The email address entered is not registered.  Please check this and try again.';
        		$this->view->error = $error;
			}   
			 		
    	// Invalid form input:	
    	} else {
	        		
	        $messages = $form->getMessages();
         	$validationErrors = array();
           	foreach (array_keys($messages) as $name) {
            	foreach($messages[$name] as $k => $v) {
                	$validationErrors[] = $v;
               	}	
          	}
                	
            $this->view->validationErrors = $validationErrors;
    	}
    }
    
    
    /**
     * Processes customer password reset request from email
     * 
     * @throws Zend_Controller_Action_Exception
     * @throws Zend_Config_Exception
     * 
     * @access public
     */
    public function resetAction()
    {
    	$form = new Customer_Form_ResetPasswordForm();
		$this->view->form = $form;
		
		// If valid input:
    	if ($this->_request->isPost()) {
    		
    		if ($form->isValid($_POST)) {
    		
	    		// Get customer ID from session:
	    		$auth = Zend_Auth::getInstance();
	        
	    		// Check customer logged in:	
	        	if ($auth->hasIdentity()) {
	        	
	        		// Get customer ID from session:
	        		$identity = $auth->getIdentity();
	        		$customerId = $identity->customer_id;
	        		
	        		// New password from form input:
	    			$newPassword = $form->getValue('password');
	    			
	    			// Update customer table:
	    			$customerService = new Falk_CustomerService();
	    			$customerService->UpdateCustomerPassword($customerId, $newPassword);
	    			
	    			// Clear record in password_reset table (and any others for this customer):
	    			$passwordResetService = new Falk_PasswordResetService(); 
	    			$passwordResetService->ClearPasswordReset($customerId);
	    			
	    			// Get Kayako User ID:
   					$kayakoUserId = $customerService->getKayakoUserId($customerId);
   					
   					// Get local config file file params for email and Kayako API:
   					$configs = $this->getInvokeArg('bootstrap')->getOption('configs');
   					$localConfig = new Zend_Config_Ini($configs['localConfigPath']);
   									   				
   					// If Kayako User ID found:
   					if ($kayakoUserId && $kayakoUserId > 0) {
   						
   						// Generate Kayako API signature:
	    				$apiKey = $localConfig->fusion->apiKey;
	   					$secretKey = $localConfig->fusion->secretKey;
	 
	   					// Generates a random string of ten digits:
	  					$salt = mt_rand();
	 
	   					// Computes the signature by hashing the salt with the secret key as the key:
	  					$signature = hash_hmac('sha256', $salt, $secretKey, true);
	 
	   					// base64 encode:
	   					$encodedSignature = base64_encode($signature);
	   					
	   					// Test user registered on Kayako application:
   						$client = new Zend_Rest_Client($localConfig->fusion->apiUrl);
  
				   		// Client arguments:
				   		$client->e('/Base/User/' . $kayakoUserId . '/');
				      	$client->apikey($apiKey);
				      	$client->salt($salt);
				      	$client->signature($encodedSignature);
		
   						// Make GET request:
   						$result = $client->get();

   						// Update kayako password if user registered	
   						if ($result->user) {
   							
		   					// Get customer full name (mandatory field for Kayako update)
		   					$fullname = $this->_helper->salutation->getDisplayNameByOption(2);
		 
		   					// Initialise REST client:
		   					$client = new Zend_Rest_Client($localConfig->fusion->apiUrl. '/Base/User/' . $kayakoUserId);
		   		
		   					// Client arguments:
		      				$client->apikey($apiKey);
		      				$client->salt($salt);
		      				$client->signature($encodedSignature);
		      				$client->fullname($fullname);
		      				$client->userpassword($newPassword);
		      				
		   					// Make POST request:
		   					$result = $client->put();
	   					
   						}
   					}
   						    			
	    			// Get customer email address:
	    			$customerNameData = $customerService->GetCustomerName($customerId)->toArray();
	    			$customerEmailAddress = $customerNameData['email'];
	    			
	    			// Saluation by customer preference:
					$name = $this->_helper->salutation->getDisplayName();

	    			// Generate email to customer confirming change of email address:
	    			$email = new Falk_Mailer_Html($localConfig->email->customerservice);
					$email->setSubject('Your Falk Culinair password has been changed')
				  	  	  ->addTo($customerEmailAddress, $name)
				  	      ->setEmailParam('name', $name)
				  	      ->setEmailParam('customerService', $this->_helper->link->customerService())
				  	      ->sendTemplate('password-updated');
				  		 
				  	// Set success message:
	    		  	$message = 'Thank you ' . $name  . '.<br/><br />Your password has been updated and you are now logged in.';
	    		  	$this->view->success = $message;
	        	
	        	} 
	        	
	        // Invalid form input:	
    		} else {
	        		
	        	$messages = $form->getMessages();
                $validationErrors = array();
                foreach (array_keys($messages) as $name) {
                    foreach($messages[$name] as $k => $v) {
                        $validationErrors[] = $v;
                    }	
                }
                	
                $this->view->validationErrors = $validationErrors;
    		}        	
    		
    	} else {
    	
	    	// Set filters and validators for GET input:
	    	$filterRules = array('pk' => array('HtmlEntities', 'StripTags', 'StringTrim'));
	    	$validatorRules = array('pk' => array('NotEmpty'));
	    	
	    	// Get input:
	    	$input = new Zend_Filter_Input($filterRules, $validatorRules);
	    	$input->setData($this->getRequest()->getParams());
	    	
	    	// If input is valid:
	    	if ($input->isValid()) {
	    		
	    		// Get customer id and expiration:
	    		$passwordResetService = new Falk_PasswordResetService();
	    		$resetResponse = $passwordResetService->GetPasswordResetData($input->pk);
	    		
	    		// Data returned on key:
	    		if (count($resetResponse) == 1) {
	    			
	    			// Convert response to an array:
	    			$reset = $resetResponse->current()->toArray();
	    			
	    			// Check if key has not expired:
	    			$date = new Zend_Date();
	    			if ($date->isEarlier(new Zend_Date($reset['expiration'], Zend_Date::TIMESTAMP))) {
	    				
	    				// Login with customer ID only:
	    				$db = Zend_Db_Table::getDefaultAdapter();
	    		
	    				// Create the auth adapter:
	    				$authAdapter = new Zend_Auth_Adapter_DbTable($db, 'customer', 'customer_id', 'customer_id');
	    				$authAdapter->setIdentity($reset['customer_id']);
	    				$authAdapter->setCredential($reset['customer_id']);
	    		
	    				// Authenticate:
	    				$result = $authAdapter->authenticate();
	    		
	    				// If result is valid:
	    				if ($result->isValid()) {
	    			
	    					$session = new Zend_Session_Namespace('falk.auth');
	    		
	    					// Store first name and user id of the user:
	    					$auth = Zend_Auth::getInstance();
	    					$storage = $auth->getStorage();
	    			
	    					$storage->write($authAdapter->getResultRowObject(array('first_name',
	    															   	   		   'customer_id')));
	    				}	
	    				
	    			} else {
	    			
	    				// Generate password expired error:	
	    				$expiredError = 'Sorry, this password reset link has now expired.  To maintain security these are only valid for 24 hours.  
	    						  		 Please get a <a href="/customer/password/lost">new reset link</a> or 
	    						         contact <a href="/support/service">customer support</a> for assistance.';
	    				$this->view->expiredError = $expiredError;
	    				
	    			}	
	    			
	    		} else {
	    			
	    			throw new Zend_Controller_Action_Exception('Page not found', 404);
	    		}
	    		
	    	} else {
	    		
	    		throw new Zend_Config_Exception('Invalid data input');
    		}
    	}
    	
    }
    
    
	/**
	 * Processes password reset request from logged in customer
	 * 
	 * @throws Zend_Controller_Action_Exception
	 * @throws Zend_Config_Exception
	 * 
	 * @access public
	 */
    public function updateAction()
    {
    	// If not logged in:
		if (!Zend_Auth::getInstance()->hasIdentity()) {
			
			// Get referring page URI:
			$url = $this->getRequest()->getRequestUri();
			
			// Set Url in session:
			$session = new Zend_Session_Namespace('falk.referrer');
			$session->requestURL = $url;
			
			// Redirect to login page:
			$this->_redirect('/customer/account/login');
		
		} else { // Check for customer_id to make sure a customer 
			
			// Get customer credentials from session:
			$auth = Zend_Auth::getInstance();
			
			if (! $auth->getIdentity()->customer_id) {
				
				// Redirect to login page:
				$this->_redirect('/customer/account/login');
			}			
		}	
    	
    		
    	// Generate the form and attach this to the view
    	$form = new Customer_Form_ResetPasswordForm();
    	$form->setAction('/customer/password/update');
		$this->view->form = $form;
		
		// If valid input:
    	if ($this->_request->isPost()) {
    		
    		if ($form->isValid($_POST)) {
    		
	    		// Get customer ID from session:
	    		$auth = Zend_Auth::getInstance();
	        
	    		// Check customer logged in:	
	        	if ($auth->hasIdentity()) {
	        	
	        		// Get customer ID from session:
	        		$identity = $auth->getIdentity();
	        		$customerId = $identity->customer_id;
	        		
	        		// New password from form input:
	    			$newPassword = $form->getValue('password');
	    			
	    			// Update customer table:
	    			$customerService = new Falk_CustomerService();
	    			$customerService->UpdateCustomerPassword($customerId, $newPassword);
	    			
	    			// Get Kayako User ID:
   					$kayakoUserId = $customerService->getKayakoUserId($customerId);
   					
   					// Get local config file file params for email and Kayako API:
   					$configs = $this->getInvokeArg('bootstrap')->getOption('configs');
   					$localConfig = new Zend_Config_Ini($configs['localConfigPath']);
   									   				
   					// If Kayako User ID found:
   					if ($kayakoUserId && $kayakoUserId > 0) {
   						
   						// Generate Kayako API signature:
	    				$apiKey = $localConfig->fusion->apiKey;
	   					$secretKey = $localConfig->fusion->secretKey;
	 
	   					// Generates a random string of ten digits:
	  					$salt = mt_rand();
	 
	   					// Computes the signature by hashing the salt with the secret key as the key:
	  					$signature = hash_hmac('sha256', $salt, $secretKey, true);
	 
	   					// base64 encode:
	   					$encodedSignature = base64_encode($signature);
	   					
	   					// Test user registered on Kayako application:
   						$client = new Zend_Rest_Client($localConfig->fusion->apiUrl);
  
				   		// Client arguments:
				   		$client->e('/Base/User/' . $kayakoUserId . '/');
				      	$client->apikey($apiKey);
				      	$client->salt($salt);
				      	$client->signature($encodedSignature);
		
   						// Make GET request:
   						$result = $client->get();

   						// Update kayako password if user registered	
   						if ($result->user) {

		   					// Get customer full name (mandatory field for Kayako update)
		   					$fullname = $this->_helper->salutation->getDisplayNameByOption(2);
		 
		   					// Initialise REST client:
		   					$client = new Zend_Rest_Client($localConfig->fusion->apiUrl. '/Base/User/' . $kayakoUserId);
		   		
		   					// Client arguments:
		      				$client->apikey($apiKey);
		      				$client->salt($salt);
		      				$client->signature($encodedSignature);
		      				$client->fullname($fullname);
		      				$client->userpassword($newPassword);
		      				
		   					// Make POST request:
		   					$result = $client->put();
	   					}	
   					}
	   					
	    			// Get customer email address:
	    			$customerNameData = $customerService->GetCustomerName($customerId)->toArray();
	    			$customerEmailAddress = $customerNameData['email'];
	    			
	    			// Saluation by customer preference:
					$name = $this->_helper->salutation->getDisplayName();
	    			
	    			// Generate email to customer confirming change of email address:
	    			$email = new Falk_Mailer_Html($localConfig->email->customerservice);
					$email->setSubject('Your Falk Culinair password has been changed')
				  	      ->addTo($customerEmailAddress, $name)
				  	      ->setEmailParam('name', $name)
				  	      ->setEmailParam('customerService', $this->_helper->link->customerService())
				  	      ->sendTemplate('password-updated');
				  		 
				  	// Set success message:
	    		  	$message = 'Thank you ' . $name  . '.<br/><br />Your password has been updated.';
	    		  	$this->view->success = $message;
	        	
	        	} 
	        	
    		} else {  // Invalid form input:	
	        		
	        	$messages = $form->getMessages();
                $validationErrors = array();
                foreach (array_keys($messages) as $name) {
                    foreach($messages[$name] as $k => $v) {
                        $validationErrors[] = $v;
                    }	
                }
                	
                $this->view->validationErrors = $validationErrors;
    		}        	
    	} 
    }
    
    
	/**
     * Action to validates the form using Ajax function
     * 
     * @return Json object
     * @access public
     */
    public function validateformAction()
    {
    	$this->_helper->viewRenderer->setNoRender();
    	$this->_helper->layout()->disableLayout();
    	
    	$form = new Customer_Form_ResetPasswordForm();
    	$form->isValid($this->_getAllParams());
    	$json = $form->getMessages();
    	
    	header('Content-type: application/json');
    	echo Zend_Json::encode($json); 	
    }
     
}

