<?php
#BEGIN_LICENSE
#-------------------------------------------------------------------------
# Module: MAMS (c) 2020-2021 by CMS Made Simple Foundation
#  An add-on module for CMS Made Simple to provide useful functions
#  and commonly used gui capabilities to other modules.
#-------------------------------------------------------------------------
# A fork of:
#
# Module: FrontEndUsers (c) 2008-2014 by Robert Campbell
#         (calguy1000@cmsmadesimple.org)
#
#-------------------------------------------------------------------------
#
# CMSMS - CMS Made Simple is (c) 2006 - 2021 by CMS Made Simple Foundation
# CMSMS - CMS Made Simple is (c) 2005 by Ted Kulp (wishy@cmsmadesimple.org)
# Visit the CMSMS Homepage at: http://www.cmsmadesimple.org
#
#-------------------------------------------------------------------------
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# However, as a special exception to the GPL, this software is distributed
# as an addon module to CMS Made Simple.  You may not use this software
# in any Non GPL version of CMS Made simple, or in any version of CMS
# Made simple that does not indicate clearly and obviously in its admin
# section that the site was built with CMS Made simple.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
# Or read it online: http://www.gnu.org/licenses/licenses.html#GPL
#
#-------------------------------------------------------------------------
#END_LICENSE
if(!defined('CMS_VERSION')) { exit; }

$returnto = \xt_param::get_string($params, 'mams_returnto');

if(isset($params['mams_cancel']))
{
  if($returnto)
  {
    $returnid = $this->resolve_alias_or_id($returnto, $returnid);
    $this->RedirectContent($returnid);
  }
}

$uid = $this->LoggedInId();

if($uid < 1)
{
  $_SESSION['mamscs']['errorid'] = 3;
  $_SESSION['mamscs']['error'] = 'not_logged_in_or_session_expired';
  $_SESSION['mamscs']['error_message'] = 'Session expired. You are not logged in.';
  // user isn't logged in
  $this->_DisplayErrorPage($id, $params, $returnid, $this->Lang('error_notloggedin'));
  
  return;
}
$result = $this->GetUserInfo($uid);
if($result[0] == FALSE)
{
  // user isn't logged in
  $this->_DisplayErrorPage($id, $params, $returnid, $result[1]);
  
  return;
}
$uinfo = $result[1];

$username = $uinfo['username'];
$password = '';

class MAMSChangeSettingsError extends \RuntimeException {}

try
{
  if(!\xt_utils::valid_form_csrf())
  {
    throw new MAMSChangeSettingsError($this->Lang('error_security'));
  }
  
  \CMSMS\HookManager::do_hook('MAMS::BeforeChangeSettings', ['uid' => $uid]);
  
  // check if user is allowed to change his username
  $consumer = mams_utils::get_auth_consumer();
  if($consumer->has_capability(mams_auth_consumer::CAPABILITY_CHANGEUSERNAME))
  {
    if(isset($params['mams_input_username']))
    {
      // user is changing his username
      $tmp = trim($params['mams_input_username']);
      if(!$this->IsValidUsername($tmp, FALSE, $uid))
      {
        throw new MAMSChangeSettingsError($this->Lang('error_invalidusername'));
      }
      if($tmp)
      {
        $username = $tmp;
      }
    }
  }
  
  // check if the user is allowed to change his password
  if($consumer->has_capability(mams_auth_consumer::CAPABILITY_CHANGEPASSWD))
  {
    // change this password
    $password = cms_html_entity_decode(trim($params['mams_input_password']));
    $repeat   = cms_html_entity_decode(trim($params['mams_input_repeatpassword']));
    if($uinfo['force_newpw'] && !$password)
    {
      throw new MAMSChangeSettingsError($this->Lang('error_requiredfield', 'password'));
    }
    
    if($uinfo['force_newpw'] && !$repeat)
    {
      throw new MAMSChangeSettingsError($this->Lang('error_requriedfield', 'repeatpassword'));
    }
    
    if($password != $repeat && $password != '')
    {
      throw new MAMSChangeSettingsError($this->Lang('error_passwordmismatch'));
    }
    
    if($password != '' && !$this->IsValidPassword($password))
    {
      throw new MAMSChangeSettingsError($this->Lang('error_invalidpassword'));
    }
  }
  
  // get property definitions
  $defnsbyname = $this->GetPropertyDefns();
  
  // Get member groups
  $groups = $this->GetMemberGroupsArray($uid);
  
  // Get group property relations into a union.
  $properties = [];
  $tmp        = [];
  foreach($groups as $onegroup)
  {
    $proprelations = $this->GetGroupPropertyRelations($onegroup['groupid']);
    $tmp           = \MAMS\RRUtils::array_merge_by_name_required($tmp, $proprelations);
    uasort($tmp, ['xt_array', 'compare_elements_by_sortorder_key']);
  }
  $properties = xt_array::to_hash($tmp, 'name');
  
  $userprops   = $this->GetUserProperties($uid);
  $deleteprops = [];
  
  // do validation of the fields.
  foreach($properties as $propname => $prop)
  {
    $fldtype  = $defnsbyname[$propname]['type'];
    $required = ($prop['required'] == 2);
    $hidden   = ($prop['required'] == 3);
    $readonly = ($prop['required'] == 4);
    
    switch($fldtype)
    {
      case MAMS::FIELDTYPE_TEXT:
        if($required)
        {
          if(!isset($params['mams_input_' . $propname]) || empty($params['mams_input_' . $propname]))
          {
            throw new MAMSChangeSettingsError($this->Lang('error_requiredfield', $defnsbyname[$propname]['prompt']));
          }
        }
      break;
      
      case MAMS::FIELDTYPE_CHECKBOX:
        if(!isset($params['mams_input_' . $propname]))
        {
          $params['mams_input_' . $propname] = 0;
        }
        if($required)
        {
          if($params['mams_input_' . $propname] == 0)
          {
            throw new MAMSChangeSettingsError($this->Lang('error_requiredfield', $defnsbyname[$propname]['prompt']));
          }
        }
      break;
      
      case MAMS::FIELDTYPE_EMAIL:
        if($required)
        {
          if(!isset($params['mams_input_' . $propname]))
          {
            throw new MAMSChangeSettingsError($this->Lang('error_invalidemailaddress'));
          }
          else
          {
            $result = $this->IsValidEmailAddress($params['mams_input_' . $propname], $uid);
            if($result[0] == FALSE)
            {
              $eml = $params['mams_input_' . $propname];
              throw new MAMSChangeSettingsError($this->Lang('error_invalidemailaddress') . " $eml");
            }
          }
        }
      break;
      
      case MAMS::FIELDTYPE_TEXTAREA:
        if($required && !isset($params['mams_input_' . $propname]))
        {
          throw new MAMSChangeSettingsError($this->Lang('error_requiredfield', $defnsbyname[$propname]['prompt']));
        }
        
        if($required && empty($params['mams_input_' . $propname]))
        {
          throw new MAMSChangeSettingsError($this->Lang('error_requiredfield', $defnsbyname[$propname]['prompt']));
        }
      break;
      
      case MAMS::FIELDTYPE_MULTISELECT:
        if($required && !isset($params['mams_input_' . $propname]))
        {
          throw new MAMSChangeSettingsError($this->Lang('error_requiredfield', $defnsbyname[$propname]['prompt']));
        }
        // encode it into a comma separated list.
        if(isset($params['mams_input_' . $propname]))
        {
          $params['mams_input_' . $propname] = implode(',', $params['mams_input_' . $propname]);
        }
        else
        {
          $params['mams_input_' . $propname] = '';
        }
      break;
      
      case MAMS::FIELDTYPE_IMAGE:
        if(
          isset($params['mams_input_' . $propname . '_clear']) &&
          $params['mams_input_' . $propname . '_clear'] == 'clear'
        )
        {
          // we're told to clear an image property, we must also
          // delete the image
          $config = cmsms()->GetConfig();
          $destDir1 = $config['uploads_path'] . '/';
          $destDir1 .= $this->GetPreference('image_destination_path', 'mams') . '/';
          $file1    = $destDir1 . $params['mams_input_' . $propname];
          
          if(is_file($file1)) { @unlink($file1); }
          
          // unset the hidden param to prevent any further processing
          $deleteprops[] = $propname;
          unset($params['mams_input_' . $propname]);
        }
        if(
          $required &&
          ((!isset($_FILES[$id . 'mams_input_' . $propname]) ||
            $_FILES[$id . 'mams_input_' . $propname]['size'] == 0) &&
           (!isset($params['mams_input_' . $propname]) || $params['mams_input_' . $propname] == ''))
        )
        {
          // but we can't find a value
          throw new MAMSChangeSettingsError($this->Lang('error_requiredfield', $propname));
        }
      break;
      
      case MAMS::FIELDTYPE_DATE:
        if(isset($params['mams_input_' . $propname . 'Month']))
        {
          $params['mams_input_' . $propname] =
            mktime(
              0, 0, 0,
              $params['mams_input_' . $propname . 'Month'],
              $params['mams_input_' . $propname . 'Day'],
              $params['mams_input_' . $propname . 'Year']
            );
          unset($params['mams_input_' . $propname . 'Month']);
          unset($params['mams_input_' . $propname . 'Day']);
          unset($params['mams_input_' . $propname . 'Year']);
        }
        
        $val = $params['mams_input_' . $propname];
        
        if(preg_match("/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/", $val))
        {
          $params['mams_input_' . $propname] = strtotime($val);
        }
        
        if($required && !isset($params['mams_input_' . $propname]))
        {
          throw new MAMSChangeSettingsError($this->Lang('error_requiredfield', $propname));
        }
      break;
      
      case MAMS::FIELDTYPE_DROPDOWN:
      case MAMS::FIELDTYPE_RADIOBUTNS:
        if($required && !isset($params['mams_input_' . $propname]))
        {
          throw new MAMSChangeSettingsError($this->Lang('error_requiredfield', $propname));
        }
      break;
      
      default:
        // we don't accept field types like this
        throw new MAMSChangeSettingsError($this->Lang('error_cantsetpropertytype', $propname));
      break;
    }
  }
  
  \CMSMS\HookManager::do_hook('MAMS::ChangeSettingsAfterValidate', ['uid' => $uid]);
  
  //
  // now we actually change the user settings
  //
  
  // password
  if($password != '' || $username != '')
  {
    $result = $this->SetUser($uid, $username, $password);
    $this->ForcePasswordChange($uid, FALSE);
    
    if($result[0] == FALSE)
    {
      throw new MAMSChangeSettingsError($this->Lang('error_problemsettinginfo') . ' ' . $result[1]);
    }
  }
  
  //
  // now delete all the properties for this user
  // in preparation for setting new ones.
  //
  $this->ForceChangeSettings($uid, FALSE);
  
  foreach($deleteprops as $one)
  {
    $this->DeleteUserPropertyFull($one, $uid, FALSE);
  }
  
  foreach($properties as $propname => $prop)
  {
    $required     = ($prop['required'] == 2);
    $hidden       = ($prop['required'] == 3);
    $readonly     = ($prop['required'] == 4);
    $fldtype      = $defnsbyname[$propname]['type'];
    $force_unique = $defnsbyname[$propname]['force_unique'];
    $val          = NULL;
    
    if(!isset($params['mams_input_' . $propname])) { continue; }
    
    if($readonly || $hidden) { continue; } // cannot set readonly or hidden fields
    
    if($fldtype == MAMS::FIELDTYPE_IMAGE)
    {
      // image type
      $val = $params['mams_input_' . $propname];
      
      if(isset($_FILES[$id . 'mams_input_' . $propname]) && $_FILES[$id . 'mams_input_' . $propname]['size'] > 0)
      {
        // It is an upload file type
        $result = $this->ManageImageUpload($id . 'mams_input_' . $propname, $propname);
        if($result[0] == FALSE)
        {
          $params['error']   = 1;
          $params['message'] = $this->Lang('error') . '&nbsp;' . $result[1];
          $this->myRedirect($id, 'changesettings', $returnid, $params);
        }
        $val = $result[1];
      }
    }
    else
    {
      $val = trim($params['mams_input_' . $propname]);
      $val = cms_html_entity_decode($val);
      
      if($fldtype == MAMS::FIELDTYPE_TEXT)
      {
        $val = filter_var($val, FILTER_SANITIZE_STRING);
      }
      else if($fldtype == MAMS::FIELDTYPE_TEXTAREA)
      {
        $val = xt_utils::clean_input_html($val);
      }
    }
    
    // check for forced unique values.
    if($val && $force_unique && !$this->IsUserPropertyValueUnique($uid, $propname, $val))
    {
      $params['error']   = 1;
      $params['message'] = $this->Lang('error_user_nonunique_field_value', $propname);
      $this->myRedirect($id, 'changesettings', $returnid, $params);
      
      return;
    }
    
    $ret = $this->SetUserPropertyFull($propname, $val, $uid);
    if($ret == FALSE)
    {
      $params['error']   = 1;
      $params['message'] = $this->Lang('error_settingproperty') . ' ' . $propname;
      $this->myRedirect($id, 'changesettings', $returnid, $params);
      
      return;
    }
  }
  
  $this->add_history($uid, 'change settings');
  
  // send a hook
  $event_params         = [];
  $event_params['name'] = $uinfo['username'];
  $event_params['id']   = $uid;
  \CMSMS\HookManager::do_hook('MAMS::OnUpdateUser', $event_params);
  
}
catch(\Exception $e)
{
  $err               = $e->GetMessage();
  $params['error']   = 1;
  $params['message'] = $e->GetMessage();
  $this->myRedirect($id, 'changesettings', $returnid, $params);
}

if($returnto)
{
  $pageid = $this->resolve_alias_or_id($returnto);
  if($pageid)
  {
    $this->RedirectContent($pageid);
  }
}
if(($url = $this->GetPostLoginURL()))
{
  redirect($url);
}
else if(($tplstr = $this->GetPreference('pageid_afterchangesettings')))
{
  $tpl = $smarty->CreateTemplate('string:' . $tplstr);
  $tpl->assign('username', $uinfo['username']);
  $tpl->assign('userinfo', $uinfo);
  $groups    = $this->GetMemberGroupsArray($this->LoggedinId());
  $groupname = $this->GetGroupName($groups[0]['groupid']);
  $tpl->assign('group', $groupname);
  $tmp = trim($tpl->fetch());
  
  if($tmp)
  {
    $pageid = $this->resolve_alias_or_id($tmp);
    if($pageid)
    {
      $this->RedirectContent($pageid);
    }
  }
}

$parms = ['message' => $this->Lang('msg_settingschanged')];
$this->myRedirect('cntnt01', 'logoutform', $returnid, $parms);
