<?php
/**
 * @copyright Copyright(c) 2016 aircheng.com
 * @file _userInfo.php
 * @brief 用户注册登录插件
 * @author nswe
 * @date 2016/4/15 8:51:13
 * @version 4.4
 */
class _userInfo extends pluginBase
{
	//注册事件
	public function reg()
	{
		//用户登录后的操作回调
		plugin::reg("userLoginCallback",$this,"userLoginCallback");

		//从cookie或者session中获取用户信息
		plugin::reg("getUser",function(){
			return self::getUser();
		});

		//获取验证通过的用户信息
		plugin::reg("isValidUser",function($data){
			list($username,$password) = $data;
			return self::isValidUser($username,$password);
		});

		//初始化用户数据控制器里面
		plugin::reg("onBeforeCreateAction",$this,"initUser");

		//注册页面拦截配置
		plugin::reg("onCreateView@simple@reg",$this,"initUserReg");
		plugin::reg("onCreateView@simple@bind_user",$this,"initUserReg");

		//用户注册方法
		plugin::reg("userRegAct",$this,"userRegAct");

		//手机注册验证码
		plugin::reg("onBeforeCreateAction@simple@_sendMobileCode",function(){
			self::controller()->_sendMobileCode = function(){$this->sendRegMobileCode();};
		});

		//邮箱验证
		plugin::reg("onBeforeCreateAction@simple@check_mail",function(){
			self::controller()->check_mail = function(){$this->check_mail();};
		});

		//用户登录校验
		plugin::reg("userLoginAct",$this,"userLoginAct");

		//登陆页面拦截
		plugin::reg('onCreateView@simple@login',function(){
			//记录callback地址
			$this->saveCallback();
		});

		//获取保存的路径地址
		plugin::reg("getCallback",function(){
			return ISession::get('callback');
		});

		//保存的路径地址
		plugin::reg("setCallback",function($url){
			return ISession::set('callback',$url);
		});

		//经验值更新
		plugin::reg('expUpdate',$this,"expUpdate");
	}

	//注册用户初始化
	public function initUserReg()
	{
		//记录callback地址
		$this->saveCallback();

		$siteObj = new Config('site_config');
		if($siteObj->reg_option == 2)
		{
			IError::show("网站当前已经关闭注册");
		}

		if($siteObj->reg_option == 3)
		{
			plugin::reg("onFinishView",function(){
				$this->view("mobileCheck");
			});
		}
	}

	//处理callback回调地址
	public function saveCallback()
	{
		$callback = IReq::get('callback') ? htmlspecialchars(IReq::get('callback')) : IUrl::getRefRoute();
		$notCallback = array('/simple/reg','/simple/login','bind_user','oauth_callback');
		if($callback)
		{
			foreach($notCallback as $key => $url)
			{
				if(strpos($callback,$url) !== false)
				{
					$callback = '';
				}
			}
			$callback ? ISession::set('callback',rtrim($callback,"/")) : '';
		}
	}

	//用户登录
	public function userLoginAct()
	{
    	$login_info = IFilter::act(IReq::get('login_info','post'));
    	$password   = IReq::get('password','post');
    	$remember   = IFilter::act(IReq::get('remember','post'));

    	if($login_info == '')
    	{
    		return '请填写用户名，邮箱，手机号';
    	}

		if(!preg_match('|\S{6,32}|',$password))
    	{
    		return '密码格式不正确,请输入6-32个字符';
    	}

    	$password = md5($password);
		if($userRow = plugin::trigger("isValidUser",array($login_info,$password)))
		{
			$this->userLoginCallback($userRow);

			//记住帐号
			if($remember == 1)
			{
				ICookie::set('loginName',$login_info);
			}
			return $userRow;
		}
		return "账号或密码错误";
	}

	//用户注册
	public function userRegAct()
	{
		$email      = IFilter::act(IReq::get('email','post'));
		$mobile     = IFilter::act(IReq::get('mobile','post'));
		$mobile_code= IFilter::act(IReq::get('mobile_code','post'));
    	$username   = IFilter::act(IReq::get('username','post'));
    	$password   = IFilter::act(IReq::get('password','post'));
    	$repassword = IFilter::act(IReq::get('repassword','post'));
    	$captcha    = IFilter::act(IReq::get('captcha','post'));

        //add by Scott Chen on 2017-11-03
        //add id_type
        $true_name   = IFilter::act(IReq::get('true_name','post'));
        $id_type    = IFilter::act(IReq::get('id_type','post'));
        $id_code   = IFilter::act(IReq::get('id_code','post'));


        $_captcha   = ISafe::get('captcha');

    	//获取注册配置参数
		$siteConfig = new Config('site_config');
		$reg_option = $siteConfig->reg_option;

		/*注册信息校验*/
		if($reg_option == 2)
		{
			return "当前网站禁止新用户注册";
		}

    	if(!preg_match('|\S{6,32}|',$password))
    	{
    		return "密码是字母，数字，下划线组成的6-32个字符";
    	}

    	if($password != $repassword)
    	{
    		return "2次密码输入不一致";
    	}

    	if(!$_captcha || !$captcha || $captcha != $_captcha)
    	{
    		return "图形验证码输入不正确";
    	}

		//邮箱验证
		if($reg_option == 1)
		{
			if(IValidate::email($email) == false)
			{
				return "邮箱格式不正确";
			}
			$memberObj = new IModel('member');
			$memberRow = $memberObj->getObj('email = "'.$email.'"');
			if($memberRow)
			{
				//再次发送激活邮件
				if($memberRow['status'] == 3)
				{
					$this->send_check_mail($email);
					exit;
				}
				else
				{
					return "邮箱已经被注册";
				}
			}
		}
		//手机验证
		else if($reg_option == 3)
		{
			if(IValidate::mobi($mobile) == false)
			{
				return "手机号格式不正确";
			}

            //add by Scott Chen on 2017-11-03
            //注册填报手机号码,绕过手机验证码
			/*$_mobileCode = ISafe::get('code'.$mobile);
			if(!$mobile_code || !$_mobileCode || $mobile_code != $_mobileCode)
			{
				return "手机号验证码不正确";
			}*/

			$memberObj = new IModel('member');
			$memberRow = $memberObj->getObj('mobile = "'.$mobile.'"');
			if($memberRow)
			{
				return "手机号已经被注册";
			}
		}

		//用户名检查
    	if(IValidate::name($username) == false)
    	{
    		return "用户名必须是由2-20个字符，可以为字母、数字、下划线和中文";
    	}
    	else
    	{
			$userObj = new IModel('user');
			$userRow = $userObj->getObj('username = "'.$username.'"');
			if($userRow)
			{
				return "用户名已经被注册";
			}
    	}

        //add by Scott Chen on 2017-11-03
        //id_type
        if ($id_type != "1") {
            return "证件类型目前只支持身份证";
        }
        if (IValidate::id_ex_18($id_code) == false) {
            return "非法身份证号码";
        }else{
            $memberDB = new IQuery('member');
            $memberDB->setWhere(" id_type='" . $id_type . "' and id_code='" . $id_code . "'");
            $memberRow = $memberDB->find();
            if($memberRow)
            {
                return "证件类型为身份证, 证件号码为: ". $id_code . ", 已经被注册";
            }
        }


        //插入user表
		$userArray = array(
			'username' => $username,
			'password' => md5($password),
		);
		$userObj->setData($userArray);
		$user_id = $userObj->add();
		if(!$user_id)
		{
			$userObj->rollback();
			return "用户创建失败";
		}

		//插入member表
		$memberArray = array(
			'user_id' => $user_id,
			'time'    => ITime::getDateTime(),
			'status'  => $reg_option == 1 ? 3 : 1,
			'mobile'  => $mobile,
			'email'   => $email,
            'true_name' => $true_name,
            'id_type' => $id_type,
            'id_code' => $id_code
		);
		$memberObj = new IModel('member');
		$memberObj->setData($memberArray);
		$memberObj->add();

		//邮箱激活帐号
		if($reg_option == 1)
		{
			$this->send_check_mail($email);
			return;
		}

		$userArray['id']       = $user_id;
		$userArray['head_ico'] = "";
		$this->userLoginCallback($userArray);

		//通知事件用户注册完毕
		plugin::trigger("userRegFinish",$userArray);
		return $userArray;
	}

	//发送注册验证码
	public function sendRegMobileCode()
	{
		$mobile   = IReq::get('mobile');
		$captcha  = IReq::get('captcha');
		$_captcha = ISafe::get('captcha');
		if(IValidate::mobi($mobile) == false)
		{
			die("请填写正确的手机号码");
		}
		if(!$captcha || !$_captcha || $captcha != $_captcha)
		{
			die("请填写正确的图形验证码");
		}

		$memberObj = new IModel('member');
		$memberRow = $memberObj->getObj('mobile = "'.$mobile.'"');
		if($memberRow)
		{
			die("手机号已经被注册");
		}

		$mobile_code = rand(1000,9999);
		$content = smsTemplate::checkCode(array('{mobile_code}' => $mobile_code));
		$result = Hsms::send($mobile,$content);
		if($result == 'success')
		{
			ISafe::set("code".$mobile,$mobile_code);
		}
		else
		{
			die($result);
		}
	}

	/**
	 * @brief 用户数据初始化赋值给控制器
	 */
	public function initUser()
	{
		$controller       = self::controller();
		$controller->user = self::getUser();
	}

	/**
	 * @brief 获取通用的注册用户数组
	 * @return array or null用户数据
	 */
	public static function getUser()
	{
		$user = array(
			'username' => ISafe::get('username'),
			'user_pwd' => ISafe::get('user_pwd'),
		);

		if($userRow = self::isValidUser($user['username'],$user['user_pwd']))
		{
			$user['user_id'] = $userRow['id'];
			$user['head_ico']= $userRow['head_ico'];
			return $user;
		}
		return null;
	}

	/**
	 * @brief  校验注册用户身份信息
	 * @param  string $login_info 用户名或者email
	 * @param  string $password   用户名的md5密码
	 * @return array or false 如果合法则返回用户数据;不合法返回false
	 */
	public static function isValidUser($login_info,$password)
	{
		$login_info = IFilter::addSlash($login_info);
		$password   = IFilter::addSlash($password);

		$userObj = new IModel('user as u,member as m');
		$where   = "(u.username = '{$login_info}' or m.email = '{$login_info}' or m.mobile='{$login_info}') and m.status = 1 and u.id = m.user_id";
		$userRow = $userObj->getObj($where);

		if($userRow && ($userRow['password'] == $password))
		{
			return $userRow;
		}
		return false;
	}

	/**
	 * @brief 用户登录
	 * @param array $userRow 用户信息登录
	 */
	public function userLoginCallback($userRow)
	{
		//用户私密数据
		ISafe::set('user_id',$userRow['id']);
		ISafe::set('username',$userRow['username']);
		ISafe::set('user_pwd',$userRow['password']);
		ISafe::set('head_ico',isset($userRow['head_ico']) ? $userRow['head_ico'] : '');
		ISafe::set('last_login',isset($userRow['last_login']) ? $userRow['last_login'] : '');

		//更新最后一次登录时间
		$memberObj = new IModel('member');
		$dataArray = array(
			'last_login' => ITime::getDateTime(),
		);
		$memberObj->setData($dataArray);
		$where     = 'user_id = '.$userRow["id"];

		//会员组更新
		$this->expUpdate($userRow['id']);
		$memberObj->update($where);
	}


	/**
	 * @brief 发送验证邮箱邮件
	 * @param $email string 邮箱地址
	 */
	public function send_check_mail($email)
	{
		if(IValidate::email($email) == false)
		{
			IError::show(403,'邮件格式错误');
		}

		$memberDB  = new IModel('member');
		$memberRow = $memberDB->getObj('email = "'.$email.'"');
		if(!$memberRow)
		{
			IError::show(403,'用户信息不存在');
		}
		$code    = base64_encode($memberRow['email']."|".$memberRow['user_id']);
		$url     = IUrl::getHost().IUrl::creatUrl("/simple/check_mail/code/{$code}");
		$content = mailTemplate::checkMail(array("{url}" => $url));

		//发送邮件
		$smtp   = new SendMail();
		$result = $smtp->send($email,"用户注册邮箱验证",$content);
		if($result===false)
		{
			IError::show(403,"发信失败,请重试！或者联系管理员查看邮件服务是否开启");
		}

		$message = "您的邮箱验证邮件已发送到{$email}！请到您的邮箱中去激活";
		self::controller()->redirect('/site/success?message='.urlencode($message).'&email='.$email);
	}

	/**
	 * @brief 验证邮箱
	 */
	public function check_mail()
	{
		$code = IReq::get("code");
		list($email,$user_id) = explode('|',base64_decode($code));
		if(IValidate::email($email) == false)
		{
			$message = "邮箱格式不正确";
		}
		else
		{
			$email   = IFilter::act($email);
			$user_id = IFilter::act($user_id,'int');

			$memberObj = new IModel("member");
			$memberRow = $memberObj->getObj(" email = '{$email}' and user_id = ".$user_id );
			if($memberRow)
			{
				//更新用户状态
				$memberObj->setData(array("status" => 1));
				$memberObj->update("user_id = ".$user_id);

				//获取用户信息
				$userObj = new IModel('user');
				$userRow = $userObj->getObj('id = '.$user_id);
				$message = "恭喜，您的邮箱激活成功！";
				$this->userLoginCallback($userRow);
			}
			else
			{
				$message = "验证信息有误，请核实！";
			}
		}
		self::controller()->redirect('/site/success?message='.urlencode($message));
	}

	/**
	 * @brief 经验值更新
	 * @param $user_id int 用户ID
	 * @param $exp     int 经验值
	 */
	public function expUpdate($user_id,$exp = 0)
	{
		$memberObj = new IModel('member');
		$memberObj->setData(array('exp' => 'exp + '.$exp));
		$result = $memberObj->update('user_id = '.$user_id,'exp');
		if($result == 0)
		{
			return;
		}

		//根据经验值查询晋升的会员组
		$memberRow = $memberObj->getObj('user_id = '.$user_id,'exp');
		if($memberRow['exp'] < 0)
		{
			$memberObj->setData(array('exp' => 0));
			$memberObj->update('user_id = '.$user_id,'exp');
			$memberRow['exp'] = 0;
		}

		$groupObj  = new IModel('user_group');
		$groupRow  = $groupObj->query($memberRow['exp'].' between minexp and maxexp and maxexp > 0','id','discount asc',1);
		$updateData = array('group_id' => 0);
		if($groupRow && $groupRow = current($groupRow))
		{
			$updateData['group_id'] = $groupRow['id'];
		}

		//如果是经验不减少则保留会员组
		if($exp >= 0 && $updateData['group_id'] == 0)
		{
			return;
		}
		$memberObj->setData($updateData);
		$memberObj->update('user_id = '.$user_id);
	}
}