<?php

/**
 * 管理中心
 */

namespace Module\Admin;

use Pyramid\Component\HttpFoundation\Response;
use Pyramid\Component\HttpFoundation\RedirectResponse;
use ErrorException;
use Kernel;

class Admin {
    
    use Dashboard,
        Common,
        WxUser,
        WxAdmin,
        Setting,
        Api,
        Develop;

    /**
     * 首页
     * @route /admin
     * @route /admin/*
     */
    public static function homepage($request) {
        if (route_get('/admin/dashboard')) {
            //return new RedirectResponse($request->getUriForPath('/admin/dashboard'));
        }
        return new RedirectResponse($request->getUriForPath('/admin/news'));
    }

    /**
     * 百度UE编辑器上传
     * @route /admin/upfilecontroller
     * @return json
     */
    public static function upfilecontroller($request, $filedata='upfile') {
        $action = $request->getParameter('action');
        switch ($action) {
            case 'config':
                echo json_encode(array(
                        /* 上传图片配置项 */
                        "imageActionName" => "uploadimage", /* 执行上传图片的action名称 */
                        "imageFieldName" => "upfile", /* 提交的图片表单名称 */
                        "imageMaxSize" => 10240000, /* 上传大小限制，单位B */
                        "imageAllowFiles" => [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 上传图片格式显示 */
                        "imageCompressEnable" => true, /* 是否压缩图片,默认是true */
                        "imageCompressBorder" => 1600, /* 图片压缩最长边限制 */
                        "imageInsertAlign" => "none", /* 插入的图片浮动方式 */
                        "imageUrlPrefix" => "", /* 图片访问路径前缀 */
                        "imagePathFormat" => "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand =>6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
                                                    /* {filename} 会替换成原文件名,配置这项需要注意中文乱码问题 */
                                                    /* {rand =>6} 会替换成随机数,后面的数字是随机数的位数 */
                                                    /* {time} 会替换成时间戳 */
                                                    /* {yyyy} 会替换成四位年份 */
                                                    /* {yy} 会替换成两位年份 */
                                                    /* {mm} 会替换成两位月份 */
                                                    /* {dd} 会替换成两位日期 */
                                                    /* {hh} 会替换成两位小时 */
                                                    /* {ii} 会替换成两位分钟 */
                                                    /* {ss} 会替换成两位秒 */
                                                    /* 非法字符 \  => * ? " < > | */
                                                    /* 具请体看线上文档 => fex.baidu.com/ueditor/#use-format_upload_filename */

                        /* 涂鸦图片上传配置项 */
                        "scrawlActionName" => "uploadscrawl", /* 执行上传涂鸦的action名称 */
                        "scrawlFieldName" => "upfile", /* 提交的图片表单名称 */
                        "scrawlPathFormat" => "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand =>6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
                        "scrawlMaxSize" => 2048000, /* 上传大小限制，单位B */
                        "scrawlUrlPrefix" => "", /* 图片访问路径前缀 */
                        "scrawlInsertAlign" => "none",

                        /* 截图工具上传 */
                        "snapscreenActionName" => "uploadimage", /* 执行上传截图的action名称 */
                        "snapscreenPathFormat" => "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand =>6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
                        "snapscreenUrlPrefix" => "", /* 图片访问路径前缀 */
                        "snapscreenInsertAlign" => "none", /* 插入的图片浮动方式 */

                        /* 抓取远程图片配置 */
                        "catcherLocalDomain" => ["127.0.0.1", "localhost", "img.baidu.com"],
                        "catcherActionName" => "catchimage", /* 执行抓取远程图片的action名称 */
                        "catcherFieldName" => "source", /* 提交的图片列表表单名称 */
                        "catcherPathFormat" => "/ueditor/php/upload/image/{yyyy}{mm}{dd}/{time}{rand =>6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
                        "catcherUrlPrefix" => "", /* 图片访问路径前缀 */
                        "catcherMaxSize" => 2048000, /* 上传大小限制，单位B */
                        "catcherAllowFiles" => [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 抓取图片格式显示 */

                        /* 上传视频配置 */
                        "videoActionName" => "uploadvideo", /* 执行上传视频的action名称 */
                        "videoFieldName" => "upfile", /* 提交的视频表单名称 */
                        "videoPathFormat" => "/ueditor/php/upload/video/{yyyy}{mm}{dd}/{time}{rand =>6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
                        "videoUrlPrefix" => "", /* 视频访问路径前缀 */
                        "videoMaxSize" => 102400000, /* 上传大小限制，单位B，默认100MB */
                        "videoAllowFiles" => [
                            ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
                            ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid"], /* 上传视频格式显示 */

                        /* 上传文件配置 */
                        "fileActionName" => "uploadfile", /* controller里,执行上传视频的action名称 */
                        "fileFieldName" => "upfile", /* 提交的文件表单名称 */
                        "filePathFormat" => "/ueditor/php/upload/file/{yyyy}{mm}{dd}/{time}{rand =>6}", /* 上传保存路径,可以自定义保存路径和文件名格式 */
                        "fileUrlPrefix" => "", /* 文件访问路径前缀 */
                        "fileMaxSize" => 51200000, /* 上传大小限制，单位B，默认50MB */
                        "fileAllowFiles" => [
                            ".png", ".jpg", ".jpeg", ".gif", ".bmp",
                            ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
                            ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
                            ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
                            ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
                        ], /* 上传文件格式显示 */

                        /* 列出指定目录下的图片 */
                        "imageManagerActionName" => "listimage", /* 执行图片管理的action名称 */
                        "imageManagerListPath" => "/ueditor/php/upload/image/", /* 指定要列出图片的目录 */
                        "imageManagerListSize" => 20, /* 每次列出文件数量 */
                        "imageManagerUrlPrefix" => "", /* 图片访问路径前缀 */
                        "imageManagerInsertAlign" => "none", /* 插入的图片浮动方式 */
                        "imageManagerAllowFiles" => [".png", ".jpg", ".jpeg", ".gif", ".bmp"], /* 列出的文件类型 */

                        /* 列出指定目录下的文件 */
                        "fileManagerActionName" => "listfile", /* 执行文件管理的action名称 */
                        "fileManagerListPath" => "/cache/images/", /* 指定要列出文件的目录 */
                        "fileManagerUrlPrefix" => "", /* 文件访问路径前缀 */
                        "fileManagerListSize" => 20, /* 每次列出文件数量 */
                        "fileManagerAllowFiles" => [
                            ".png", ".jpg", ".jpeg", ".gif", ".bmp",
                            ".flv", ".swf", ".mkv", ".avi", ".rm", ".rmvb", ".mpeg", ".mpg",
                            ".ogg", ".ogv", ".mov", ".wmv", ".mp4", ".webm", ".mp3", ".wav", ".mid",
                            ".rar", ".zip", ".tar", ".gz", ".7z", ".bz2", ".cab", ".iso",
                            ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf", ".txt", ".md", ".xml"
                        ] /* 列出的文件类型 */

                )); exit;
                break;
            case 'uploadimage':
            case 'uploadscrawl':
            case 'uploadvideo':
            case 'uploadfile':
                return self::upfile($request, $filedata);
                break;
                
            case 'listimage':
                break;
            case 'listfile':
                break;

            case 'catchimage':
                $result = include("action_crawler.php");
                break;

            default:
                $result = json_encode(array(
                    'state'=> '请求地址出错'
                ));
            break;
        }
    }

    /**
     * 文件上传
     * @route /admin/upload
     * @return json
     */
    public static function upload($request, $filedata='Filedata') {
        $token = $request->getParameter('token','');
        $stamp = $request->getParameter('stamp','0');
        if (!validateFormToken($stamp, $token, 1200)) {
            return new Response(json_encode(array('state'=>'FAIL', 'msg'=>'Token已过期或不合法')));
        }
        return self::upfile($request, $filedata);
    }

    /**
     * 百度编辑器上传
     * @route /admin/upfile
     * @return json
     */
    public static function upfile($request, $filedata='upfile') {
        $file = $request->files->getParameter($filedata);
        $folder = $request->getParameter('folder','');
        $folder = preg_replace('|[^\w]|','',$folder);
        $compress = $request->getParameter('compress','1');
        if (!empty($file) && !empty($file['tmp_name'])) {
            $path = config()->get('webRoot');
            $ext  = strtolower(strrchr($file['name'], '.'));
            $ext  = $ext ? $ext : '.jpg';
            if (!$folder) {
                $url  = '/cache/images/' . date('Ymd') . '/' . microtime(true) . $ext;
            } else {
                $url  = '/cache/'.$folder.'/' . date('Ymd') . '/' . microtime(true) . $ext;
            }
            if (!is_dir(dirname($path.$url))) {
                mkdir(dirname($path.$url), 0777, true);
            }
            if (!move_uploaded_file($file['tmp_name'], $path.$url)) {
                copy($file['tmp_name'], $path.$url);
            }
            //压缩图片
            if ($compress && in_array($ext,array('.jpg','.png','.gif'))) {
                $width = (int) $request->getParameter('width','0');
                $height = (int) $request->getParameter('height','0');
                $img = new \Pyramid\Component\Image\Image($path.$url);
                if ($width || $height) {
                    $img->autoCrop($width,$height)->autoSave($path.$url);
                } else {
                    $info = $img->info();
                    if ($info && $info['width'] > 1600) {
                        $img->autoCrop(1600)->autoSave($path.$url);
                    }
                }
            }
            exit(json_encode(array(
                        'state' => 'SUCCESS',
                        'msg'   => 'OK',
                        'url'   => $url,
                        'name'  => basename($url),
                        'type'  => $ext,
                        'size'  => $file['size'],
                        'originalName' => $file['name'],
                      )));
        }
        exit(json_encode(array('state'=>'FAIL', 'msg'=>'上传失败')));
    }

    /**
     * 登陆
     * @route /admin/login
     */
    public static function login($request) {
        //7天免密登录
        $sid = $request->cookies->getParameter('auto7days');
        if ($sid) {
            if ($sess = db_query("select * from {sessions} where sid=:sid", array(':sid'=>$sid))->fetchObject()) {
                if ($sess->timestamp >= time() && $sess->ip == $request->getIP()) {
                    $user = entity_object('user', $sess->session);
                    db_query("update {sys_user} set accessed=".time()." where uid={$user->uid} ");
                    session()->set('admin', $user);
                    return new RedirectResponse($request->getUriForPath('/admin'));
                }
            }
        }
        if ($request->post->getParameters()) {
            $auto7days = $request->post->getParameter('auto7days', '');
            $username = $request->post->getParameter('username', '');
            $password = $request->post->getParameter('password', '');
            $vcode = $request->post->getParameter('vcode', '');
            $captcha = session()->get('captcha');
            if (!$vcode || $vcode != $captcha) {
                return new Response(array('state'=>'ERROR', 'msg'=>'验证码错误'));
            }
            $password = cryptojs_aes_decrypt($password, md5($username), $vcode);
            $user = entity_object('user', array(), array('username'=>$username));
            if ($user && pyramid_password_verify($password, $user->password)) {
                db_query("update {sys_user} set accessed=".time()." where uid={$user->uid} ");
                session()->set('admin', $user);
                //设置7天免密登录
                if ($auto7days) {
                    $sid = md5(session_id());
                    $expires = time() + 86400*7;
                    db_merge('sessions')
                        ->key(array(
                            'sid' => $sid,
                        ))
                        ->fields(array(
                            'sid' => $sid,
                            'timestamp' => $expires,
                            'session' => $user->uid,
                            'ip' => $request->getIP(),
                        ))
                        ->execute();
                    setcookie('auto7days', $sid, $expires, '/', null, false, true);
                }
                return new Response(array('state'=>'SUCCESS', 'msg'=>'登录成功'));
            } else {
                return new Response(array('state'=>'ERROR', 'msg'=>'用户名或密码错误或帐号被锁定'));
            }
        }
        $captcha = random(4, '123467890abcdefghjmnpqrtuxyz');
        session()->set('captcha', $captcha);
        return new Response(render('/admin/login.html', array(
            'captcha' => $captcha,
        )));
    }
    
    /**
     * 登陆[废弃]
     * old route /admin/login
     */
    private static function deleted_login($request) {
        //7天免密登录
        $sid = $request->cookies->getParameter('auto7days');
        if ($sid) {
            if ($sess = db_query("select * from {sessions} where sid=:sid", array(':sid'=>$sid))->fetchObject()) {
                if ($sess->timestamp >= time() && $sess->ip == $request->getIP()) {
                    $user = entity_object('user', $sess->session);
                    db_query("update {sys_user} set accessed=".time()." where uid={$user->uid} ");
                    session()->set('admin', $user);
                    return new RedirectResponse($request->getUriForPath('/admin'));
                }
            }
        }
        if ($request->post->getParameters()) {
            $auto7days = $request->post->getParameter('auto7days', '');
            $username = $request->post->getParameter('username', '');
            $password = $request->post->getParameter('password', '');
            $user = entity_object('user', array(), array('username'=>$username));
            if ($user && pyramid_password_verify($password, $user->password)) {
                db_query("update {sys_user} set accessed=".time()." where uid={$user->uid} ");
                session()->set('admin', $user);
                //设置7天免密登录
                if ($auto7days) {
                    $sid = session_id();
                    $expires = time() + 86400*7;
                    db_insert('sessions')
                        ->fields(array(
                            'sid' => $sid,
                            'timestamp' => $expires,
                            'session' => $user->uid,
                            'ip' => $request->getIP(),
                        ))
                        ->execute();
                    setcookie('auto7days', $sid, $expires, '/', null, false, true);
                }
                return new Response(array('state'=>'SUCCESS', 'msg'=>'登录成功'));
            } else {
                return new Response(array('state'=>'ERROR', 'msg'=>'用户名或密码错误或帐号被锁定'));
            }
        }
        return new Response(render('/admin/login.html'));
    }

    /**
     * 登出
     * @route /admin/logout
     */
    public static function logout($request) {
        session()->delete('admin')->flush();
        $sid = $request->cookies->getParameter('auto7days', '');
        setcookie('auto7days', '', time(), '/', null, false, true);
        db_query("delete from {sessions} where sid=:sid", array(':sid'=>$sid));
        return new RedirectResponse($request->getUriForPath('/admin/login'));
    }

    /**
     * 修改密码
     * @route /admin/password
     */
    public static function settingPassword($request) {
        if ($request->post->getParameters()) {
            $uid = session()->get('admin')->uid;
            $oldpassword = $request->post->getParameter('oldpassword');
            $newpassword = $request->post->getParameter('newpassword');
            $cfmpassword = $request->post->getParameter('cfmpassword');
            if (!$oldpassword || !$newpassword || $newpassword != $cfmpassword) {
                return new RedirectResponse($request->getUriForPath('/admin/password'), 3, '信息不完整');
            }
            $dbpassword = db_query("select password from {sys_user} where uid=:uid", array(':uid'=>$uid))->fetchField();
            if (pyramid_password_verify($oldpassword, $dbpassword)) {
                db_update('sys_user')
                    ->fields(array('password'=>pyramid_password_hash($newpassword)))
                    ->condition('uid', $uid)
                    ->execute();
                return new RedirectResponse($request->getUriForPath('/admin/password'), 3, '密码修改成功');
            } else {
                return new RedirectResponse($request->getUriForPath('/admin/password'), 3, '旧密码输入错误');
            }
        }
        return new Response(render('/admin/password.html'));
    }

}

/**
 * 凡是admin开头的,都需要登录,以及部分数据全局初始化
 */
Kernel::dispatch(function($request) {
    if (!$request->route->contain('/admin')) {
        return ;
    }
    //登录地址||上传文件 放行
    if ($request->route->contain('/admin/login') || $request->route->contain('/admin/upload')) {
        return ;
    }
    //验证登陆的用户
    if (!$session = session()->get('admin')) {
        header("Location: " . $request->getUriForPath('/admin/login')); exit;
    }
    $admin = entity_object('user', array($session->uid));
    theme()->addGlobal('admin', $admin);
    $request->setParameter('admin', $admin);
    //权限判断
    if ($accesses = $request->route->get('access')) {
        foreach($accesses as $access) {
            user_access($access, $admin);
        }
    }
    //写入日志
    oplog($request, $session->uid);
    //初始化菜单 (ACL)
    $menus = db_query("select * from {sys_menu} where status=1 order by sortrank asc")->fetchAllAssoc('id', \PDO::FETCH_ASSOC);
    foreach ($menus as $k=>$v) {
        //去除没有权限的route
        if ($admin->uid != 1) {
            foreach (\Pyramid\Component\Route\Route::get() as $routes) {
                if (isset($routes[ltrim($v['path'],'/')])) {
                    $route = $routes[ltrim($v['path'],'/')];
                    if (!empty($route['access'])) {
                        foreach ($route['access'] as $perm) {
                            if (!isset($admin->permissions[$perm])) {
                                unset($menus[$k]);
                                continue 3;
                            }
                        }
                    }
                }
            }
        }
        //设置菜单高亮选中
        if ($request->route->contain($v['path'])) {
            $menus[$k]['active'] = true;
        } else {
            $menus[$k]['active'] = false;
        }
    }
    $menus = data_to_tree($menus, 0, 'pid');
    $submenus = array();
    foreach ($menus as $k=>$v) {
        if ($v['active'] == true && isset($v['child'])) {
            $submenus = $v['child'];
        }
    }
    theme()->addGlobal('menus', $menus);
    theme()->addGlobal('submenus', $submenus);
    //唯一token标识
    $token = md5(session_id() . $session->uid);
    theme()->addGlobal('global_token', $token);
    //表单的token
    theme()->addGlobal('form_token', generateFormToken());

});


//生成一个表单token
function generateFormToken() {
    $stamp = time();
    $token = md5(strrev($stamp).LICENSE.$stamp);
    return array('token'=>$token, 'stamp'=>$stamp);
}

//验证表单token
function validateFormToken($stamp, $token, $time = 0) {
    if ($time && abs(time()-(int)$stamp) > $time) {
        return false;
    }
    $value = md5(strrev($stamp).LICENSE.$stamp);
    return $token == $value;
}

//验证Token
function validateRequestToken($request, $time = 0) {
    $token = $request->getParameter('token','');
    $stamp = $request->getParameter('stamp','0');
    if (!validateFormToken($stamp, $token, $time)) {
        throw new ErrorException('非法或过期的Token请求');
    }
}

//用户日志记录
function oplog($request, $uid = 0) {
    /*
    $queryString = $request->getQueryString();
    db_insert('sys_oplog')
        ->fields(array(
            'uid'     => (int) $uid,
            'ip'      => $request->getIp(),
            'method'  => $request->getMethod(),
            'referer' => $request->getReferer(),
            'query'   => $queryString ? $queryString : '',
            'path'    => $request->getPathInfo(),
            'created' => time(),
        ))
        ->execute();
    */
}


//权限的描述 暂时先放这里
permission_register(array(
    'root' => array(
        'bundle'        => '管理员',
        'title'         => '系统级开发组',
        'description'   => '',
    ),
    'administrator' => array(
        'bundle'        => '管理员',
        'title'         => '超级管理员组',
        'description'   => '',
    ),
));
