HomeBaseController.php 16.6 KB
<?php
// +----------------------------------------------------------------------
// | bronet [ 以客户为中心 以奋斗者为本 ]
// +----------------------------------------------------------------------
// | Copyright (c) 2013-2017 http://www.bronet.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +---------------------------------------------------------------------
// | Author: Dean <zxxjjforever@163.com>
// +----------------------------------------------------------------------
namespace cmf\controller;

use app\user\model\UserModel;
use think\Db;
use app\admin\model\ThemeModel;
use think\View;

class HomeBaseController extends BaseController
{

    public function _initialize()
    {
        // 监听home_init
        hook('home_init');
        parent::_initialize();
        $siteInfo = cmf_get_site_info();
        View::share('site_info', $siteInfo);
    }

    public function _initializeView()
    {
        $cmfThemePath    = config('cmf_theme_path');
        $cmfDefaultTheme = cmf_get_current_theme();

        $themePath = "{$cmfThemePath}{$cmfDefaultTheme}";

        $root = cmf_get_root();
        //使cdn设置生效
        $cdnSettings = cmf_get_option('cdn_settings');
        if (empty($cdnSettings['cdn_static_root'])) {
            $viewReplaceStr = [
                '__ROOT__'     => $root,
                '__TMPL__'     => "{$root}/{$themePath}",
                '__STATIC__'   => "{$root}/static",
                '__WEB_ROOT__' => $root
            ];
        } else {
            $cdnStaticRoot  = rtrim($cdnSettings['cdn_static_root'], '/');
            $viewReplaceStr = [
                '__ROOT__'     => $root,
                '__TMPL__'     => "{$cdnStaticRoot}/{$themePath}",
                '__STATIC__'   => "{$cdnStaticRoot}/static",
                '__WEB_ROOT__' => $cdnStaticRoot
            ];
        }

        $viewReplaceStr = array_merge(config('view_replace_str'), $viewReplaceStr);
        config('template.view_base', "{$themePath}/");
        config('view_replace_str', $viewReplaceStr);

        $themeErrorTmpl = "{$themePath}/error.html";
        if (file_exists_case($themeErrorTmpl)) {
            config('dispatch_error_tmpl', $themeErrorTmpl);
        }

        $themeSuccessTmpl = "{$themePath}/success.html";
        if (file_exists_case($themeSuccessTmpl)) {
            config('dispatch_success_tmpl', $themeSuccessTmpl);
        }


    }

    /**
     * 加载模板输出
     * @access protected
     * @param string $template 模板文件名
     * @param array $vars 模板输出变量
     * @param array $replace 模板替换
     * @param array $config 模板参数
     * @return mixed
     */
    protected function fetch($template = '', $vars = [], $replace = [], $config = [])
    {
        $template = $this->parseTemplate($template);
        $more     = $this->getThemeFileMore($template);
        $this->assign('theme_vars', $more['vars']);
        $this->assign('theme_widgets', $more['widgets']);
        return parent::fetch($template, $vars, $replace, $config);
    }

    /**
     * 自动定位模板文件
     * @access private
     * @param string $template 模板文件规则
     * @return string
     */
    private function parseTemplate($template)
    {
        // 分析模板文件规则
        $request = $this->request;
        // 获取视图根目录
        if (strpos($template, '@')) {
            // 跨模块调用
            list($module, $template) = explode('@', $template);
        }

        $viewBase = config('template.view_base');

        if ($viewBase) {
            // 基础视图目录
            $module = isset($module) ? $module : $request->module();
            $path   = $viewBase . ($module ? $module . DS : '');
        } else {
            $path = isset($module) ? APP_PATH . $module . DS . 'view' . DS : config('template.view_path');
        }

        $depr = config('template.view_depr');
        if (0 !== strpos($template, '/')) {
            $template   = str_replace(['/', ':'], $depr, $template);
            $controller = cmf_parse_name($request->controller());
            if ($controller) {
                if ('' == $template) {
                    // 如果模板文件名为空 按照默认规则定位
                    $template = str_replace('.', DS, $controller) . $depr . $request->action();
                } elseif (false === strpos($template, $depr)) {
                    $template = str_replace('.', DS, $controller) . $depr . $template;
                }
            }
        } else {
            $template = str_replace(['/', ':'], $depr, substr($template, 1));
        }
        return $path . ltrim($template, '/') . '.' . ltrim(config('template.view_suffix'), '.');
    }

    /**
     * 获取模板文件变量
     * @param string $file
     * @param string $theme
     * @return array
     */
    private function getThemeFileMore($file, $theme = "")
    {

        //TODO 增加缓存
        $theme = empty($theme) ? cmf_get_current_theme() : $theme;

        // 调试模式下自动更新模板
        if (APP_DEBUG) {
            $themeModel = new ThemeModel();
            $themeModel->updateTheme($theme);
        }

        $themePath = config('cmf_theme_path');
        $file      = str_replace('\\', '/', $file);
        $file      = str_replace('//', '/', $file);
        $file      = str_replace(['.html', '.php', $themePath . $theme . "/"], '', $file);

        $files = Db::name('theme_file')->field('more')->where(['theme' => $theme])->where(function ($query) use ($file) {
            $query->where(['is_public' => 1])->whereOr(['file' => $file]);
        })->select();

        $vars    = [];
        $widgets = [];
        foreach ($files as $file) {
            $oldMore = json_decode($file['more'], true);
            if (!empty($oldMore['vars'])) {
                foreach ($oldMore['vars'] as $varName => $var) {
                    $vars[$varName] = $var['value'];
                }
            }

            if (!empty($oldMore['widgets'])) {
                foreach ($oldMore['widgets'] as $widgetName => $widget) {

                    $widgetVars = [];
                    if (!empty($widget['vars'])) {
                        foreach ($widget['vars'] as $varName => $var) {
                            $widgetVars[$varName] = $var['value'];
                        }
                    }

                    $widget['vars']       = $widgetVars;
                    $widgets[$widgetName] = $widget;
                }
            }
        }

        return ['vars' => $vars, 'widgets' => $widgets];
    }

    public function checkUserLogin()
    {
        $userId = cmf_get_current_user_id();
        if (empty($userId)) {
            $this->error("用户尚未登录", url("user/login/index"));
        }
    }

    /**
     * 检查微信用户登录
     * @param int $type 1-公众号普通登录,2-验证关注公众号才可登录
     * @throws \think\Exception
     * @throws \think\db\exception\DataNotFoundException
     * @throws \think\db\exception\ModelNotFoundException
     * @throws \think\exception\DbException
     * @throws \think\exception\PDOException
     */
    public function checkWeChatUserLogin($type=2)
    {

        if (strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') === false) {
            //todo 取消下面注释可模拟用户在非微信浏览器下登录,方便本地测试
            /*$userModel = new UserModel();
            $userWhere = ['user_id' => 1, 'app_id' => config('wx_app_id')];
            $user = $userModel->getUserInfo($userWhere);
            cmf_update_current_user($user);*/
        }

        $userId = cmf_get_current_user_id();
        if (empty($userId)) {
            $appId=config('wx_app_id');
            $appSecret=config('wx_app_secret');
            //通过code换取网页授权access_token和openid
            $code = $this->request->get('code');
            if(empty($code)){
                $url = urlencode('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']);
                header('Location: https://open.weixin.qq.com/connect/oauth2/authorize?appid='.$appId.'&redirect_uri='.$url.'&response_type=code&scope=snsapi_userinfo&state=STATE#wechat_redirect');
            }
            //通过code换取网页授权access_token和openid
            $openidUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" .$appId . "&secret=" . $appSecret . "&code=" . $code . "&grant_type=authorization_code";
            $openidData = json_decode(file_get_contents($openidUrl), true);
            if (empty($openidData['openid'])) {
                $this->error($openidData['errcode'].':'.$openidData['errmsg']);
            }else {
                $openid=$openidData['openid'];
                $findThirdPartyUser = Db::name("third_party_user")
                    ->where('openid', $openid)
                    ->where('app_id', $appId)
                    ->find();
                $currentTime = time();
                $ip          = $this->request->ip(0, true);
                if ($findThirdPartyUser) {
                    $token = cmf_generate_user_token($findThirdPartyUser['user_id'], 'public');

                    $userData = [
                        'last_login_ip'   => $ip,
                        'last_login_time' => $currentTime,
                        'login_times'     => ['exp', 'login_times+1']
                    ];

                    if (isset($openidData['unionId'])) {
                        $userData['union_id'] = $openidData['unionId'];
                    }

                    $row1=Db::name("third_party_user")
                        ->where('openid', $openid)
                        ->where('app_id', $appId)
                        ->update($userData);
                    $userInfo=Db::name("third_party_user")
                        ->where('openid', $openid)
                        ->where('app_id', $appId)->find();
                    unset($userData['login_times']);
                    $userData['last_login_type']='public';
                    $row2=Db::name("user")
                        ->where('id', $userInfo['user_id'])
                        ->update($userData);

                    if($row1!==false&&$row2!==false){
                        $userModel=new UserModel();
                        $user=$userModel->getUserInfo(['user_id'=>$userInfo['user_id'],'app_id'=>$appId]);
                        cmf_update_current_user($user);
                        session('token',$token);
                        Db::commit();
                    }else{
                        Db::rollback();
                    }
                }else{
                    switch ($type){
                        case 1:
                            $userinfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" . $openidData['access_token'] . "&openid=" . $openidData['openid'] . "&lang=zh_CN";
                            $userinfoData = json_decode(file_get_contents($userinfoUrl), true);
                            $nickname=$userinfoData['nickname'];
                            Db::startTrans();
                            $userId = Db::name("user")->insertGetId([
                                'create_time'     => $currentTime,
                                'user_status'     => 1,
                                'user_type'       => 2,
                                'sex'             => $userinfoData['sex'],
                                'user_nickname'   => $nickname,
                                'avatar'          => $userinfoData['headimgurl'],
                                'last_login_ip'   => $ip,
                                'last_login_time' => $currentTime,
                                'union_id'        => isset($userinfoData['unionid']) ? $userinfoData['unionid'] : '',
                            ]);

                            $row=Db::name("third_party_user")->insert([
                                'openid'          => $openid,
                                'user_id'         => $userId,
                                'third_party'     => 'public',
                                'nickname'        => $nickname,
                                'app_id'          => $appId,
                                'last_login_ip'   => $ip,
                                'union_id'        => isset($userinfoData['unionid']) ? $userinfoData['unionid'] : '',
                                'last_login_time' => $currentTime,
                                'create_time'     => $currentTime,
                                'login_times'     => 1,
                                'status'          => 1,
                                'more'            => json_encode($userinfoData)
                            ]);
                            if($userId && $row){
                                $token = cmf_generate_user_token($userId, 'public');
                                $userModel=new UserModel();
                                $user=$userModel->getUserInfo(['user_id'=>$userId,'app_id'=>$appId]);
                                cmf_update_current_user($user);
                                session('token',$token);
                                Db::commit();
                            }else{
                                Db::rollback();
                            }
                            break;
                        case 2:
                            $token = getAccessToken();
                            $userinfoUrl = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" . $token . "&openid=" . $openidData['openid'] . "&lang=zh_CN";
                            $userinfoData = json_decode(file_get_contents($userinfoUrl), true);
                            if($userinfoData['subscribe']==1){
                                $nickname=$userinfoData['nickname'];
                                Db::startTrans();
                                $userId = Db::name("user")->insertGetId([
                                    'create_time'     => $currentTime,
                                    'user_status'     => 1,
                                    'user_type'       => 2,
                                    'sex'             => $userinfoData['sex'],
                                    'user_nickname'   => $nickname,
                                    'avatar'          => $userinfoData['headimgurl'],
                                    'last_login_ip'   => $ip,
                                    'last_login_time' => $currentTime,
                                    'union_id'        => isset($userinfoData['unionid']) ? $userinfoData['unionid'] : '',
                                ]);

                                $row=Db::name("third_party_user")->insert([
                                    'openid'          => $openid,
                                    'user_id'         => $userId,
                                    'third_party'     => 'public',
                                    'nickname'        => $nickname,
                                    'app_id'          => $appId,
                                    'last_login_ip'   => $ip,
                                    'union_id'        => isset($userinfoData['unionid']) ? $userinfoData['unionid'] : '',
                                    'last_login_time' => $currentTime,
                                    'create_time'     => $currentTime,
                                    'login_times'     => 1,
                                    'status'          => 1,
                                    'more'            => json_encode($userinfoData)
                                ]);
                                if($userId && $row){
                                    $token = cmf_generate_user_token($userId, 'public');
                                    $userModel=new UserModel();
                                    $user=$userModel->getUserInfo(['user_id'=>$userId,'app_id'=>$appId]);
                                    cmf_update_current_user($user);
                                    session('token',$token);
                                    Db::commit();
                                }else{
                                    Db::rollback();
                                }
                            }else{
                                $this->redirect("https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzIzNDkzNzQzMg==#wechat_redirect");
                            }
                            break;
                        default:
                            $this->error("用户尚未登录", "https://mp.weixin.qq.com/mp/profile_ext?action=home&__biz=MzIzNDkzNzQzMg==&scene=110#wechat_redirect");
                    }
                }
            }
        }
    }

}