upload/src/applications/native/controller/AttachController.php
<?php

/**
 * 附件下载相关接口
 *
 * @fileName: AttachController.php
 * @author: yuliang<yuliang.lyl@alibaba-inc.com>
 * @license: http://www.phpwind.com
 * @version: $Id
 * @lastchange: 2014-12-16 19:08:17
 * @desc: 
 * */
defined('WEKIT_VERSION') || exit('Forbidden');

Wind::import('APPS:native.controller.NativeBaseController');

class AttachController extends NativeBaseController {

    public function run() {

    }
    
     /** 
     * 附件下载前的权限检测                                                                                                                                 
     * @access public
     * @return void
     * @example
     * <pre>
     * /index.php?m=native&c=attach&a=check&aid=77&_json=1
     * </pre>
     */
    public function checkAction() {
        //检测用户是否登录
        $this->uid || $this->showError("您还没有登录");
        $this->loginUser = new PwUserBo($this->uid);
        //参数检测
        $aid = $this->getInput('aid');
        $aid || $this->showError("参数错误");
        //获取附件详细信息
        $attach = Wekit::load('attach.PwThreadAttach')->getAttach($aid);
        if (!$attach) {
                $this->showError('BBS:thread.buy.attach.error');
        }
        //免费附件、附件上传者 可以下载
        if(!$attach['cost'] || $this->uid == $attach['created_userid']){
            $this->setOutput(array('state'=>1,'message'=>''),'data');
            $this->showMessage('NATIVE:data.success'); 
        }
        //收费附件已购买用户可下载
        $attachbuy = Wekit::load('attach.PwThreadAttachBuy');
        if ($attachbuy->getByAidAndUid($attach['aid'], $this->uid)) {
            $this->setOutput(array('state'=>1,'message'=>''),'data');
            $this->showMessage('NATIVE:data.success'); 
        }
        //其余用户提示需要购买，获取用户当前的余额
        $creditvalue = $attach['cost'];
        $credittype = $attach['ctype'];
        Wind::import('SRV:credit.bo.PwCreditBo');
        $creditBo = PwCreditBo::getInstance();
        $creditname = $creditBo->cType[$attach['ctype']];
        $userCredit = $this->loginUser->getCredit($attach['ctype']);
        
        if($userCredit >= $creditvalue){//余额充足的提示是否购买
            $this->setOutput(array('state'=>2,'message'=>"该附件售价：{$creditvalue}{$creditname}， 您目前的{$creditname}：{$userCredit} 您确定要下载吗？ "),'data');
            $this->showMessage('NATIVE:data.success');
        }else{//余额不足的提示无法购买
            $this->setOutput(array('state'=>3,'message'=>"该附件售价：{$creditvalue}{$creditname}， 您目前的{$creditname}：{$userCredit} 余额不足不能下载。 "),'data');
            $this->showMessage('NATIVE:data.success');
        }
    }

    /**
     * 附件下载
     * /index.php?m=native&c=attach&a=download&aid=77
     */
    public function downloadAction() {
//        $this->uid = 1;
            $this->loginUser = new PwUserBo($this->uid);
//        var_dump($this->loginUser);
            $aid = (int)$this->getInput('aid', 'get');
            $submit = (int)$this->getInput('submit', 'post');
            $attach = Wekit::load('attach.PwThreadAttach')->getAttach($aid);
            if (!$attach) {
                    $this->showError('BBS:thread.buy.attach.error');
            }
            Wind::import('SRV:forum.bo.PwForumBo');
            $forum = new PwForumBo($attach['fid']);
            if (!$forum->isForum()) {
                    $this->showError('data.error');
            }
            
            if ($attach['cost'] && !$this->loginUser->isExists()) {
                    $this->showError('download.fail.login.not','bbs/attach/download');
            }
            if (!$forum->allowDownload($this->loginUser)) {
                    if (!$this->loginUser->isExists()) {
                            $this->showError('download.fail.login.not','bbs/attach/download');
                    }
                    $this->showError(array('BBS:forum.permissions.download.allow', array('{grouptitle}' => $this->loginUser->getGroupInfo('name'))));
            }
            if (!$forum->foruminfo['allow_download'] && !$this->loginUser->getPermission('allow_download')) {
                    if (!$this->loginUser->isExists()) {
                            $this->showError('download.fail.login.not','bbs/attach/download');
                    }
                    $this->showError(array('permission.download.allow', array('{grouptitle}' => $this->loginUser->getGroupInfo('name'))));
            }
            Wind::import('SRV:credit.bo.PwCreditBo');
            $creditBo = PwCreditBo::getInstance();
            // 购买积分检查
            if (($attach = $this->_checkAttachCost($attach)) instanceof PwError) {
                    $this->showError($attach->getError());
            }
            // 下载积分检查
            if (($reduceDownload = $this->_checkAttachDownload('download_att', $attach, $forum)) instanceof PwError) {
                    $this->showError($reduceDownload->getError());
            }

            //下载积分提示
            $lang = Wind::getComponent('i18n');
            if (1 == $this->loginUser->getPermission('allow_download') && $reduceDownload && $attach['cost']) {
                    $dataShow = $lang->getMessage('BBS:thread.attachbuy.message.all', array('{buyCount}' =>-$attach['cost'].$creditBo->cType[$attach['ctype']], '{downCount}' => rtrim($reduceDownload, ',')));
            } elseif (1 == $this->loginUser->getPermission('allow_download') && $reduceDownload && !$attach['cost']) {
                    $dataShow = $lang->getMessage('BBS:thread.attachbuy.message.download', array('{downCount}' => rtrim($reduceDownload, ',')));
            } elseif ($attach['cost']) {
                    $dataShow = $lang->getMessage('BBS:thread.attachbuy.message.buy', array('{count}' => $this->loginUser->getCredit($attach['ctype']).$creditBo->cType[$attach['ctype']], '{buyCount}' => -$attach['cost'].$creditBo->cType[$attach['ctype']]));
            } else {
                    $dataShow = $lang->getMessage('BBS:thread.attachbuy.message.success');
            }
            
            $submit = 1;
            !$submit && $this->showMessage($dataShow);
            
    
            //购买积分操作
            $this->_operateBuyCredit($attach);

            // 下载积分
            if ($reduceDownload) {
                    Wind::import('SRV:attach.dm.PwThreadAttachBuyDm');
                    $dm = new PwThreadAttachBuyDm();
                    $dm->setAid($aid)
                            ->setCreatedUserid($this->loginUser->uid)
                            ->setCreatedTime(Pw::getTime())
                            ->setCtype($attach['ctype'])
                            ->setCost($attach['cost']);
                    Wekit::load('attach.PwThreadAttachDownload')->add($dm);
                    $this->_operateCredit('download_att', $forum);
            }
            //更新附件点击数
            Wind::import('SRV:attach.dm.PwThreadAttachDm');
            $dm = new PwThreadAttachDm($aid);
            $dm->addHits(1);
            Wekit::load('attach.PwThreadAttach')->updateAttach($dm);
            
            $filename = basename($attach['path']);
            $fileext = substr(strrchr($attach['path'], '.'), 1);
            $filesize = 0;
            if (strpos(Wind::getApp()->getRequest()->getServer('HTTP_USER_AGENT'), 'MSIE') !== false && $fileext == 'torrent') {
                    $attachment = 'inline';
            } else {
                    $attachment = 'attachment';
            }
            $attach['name'] = trim(str_replace('&nbsp;', ' ', $attach['name']));
            if (strtoupper(Wekit::V('charset')) == 'UTF-8') {
                    $attach['name'] = Pw::convert($attach['name'], "gbk", 'utf-8');
            }

            $filesize = 0;
            $fgeturl = Wind::getComponent('storage')->getDownloadUrl($attach['path']);

            if (strpos($fgeturl, 'http') !== 0) {
                    if (!is_readable($fgeturl)) {
                            $this->showError('BBS:thread.buy.attach.error');
                    }
                    $filesize = filesize($fgeturl);
            }

            $timestamp = Pw::getTime();
            $ctype = '';
            switch ($fileext) {
                    case "pdf":
                            $ctype = "application/pdf";
                            break;
                    case "rar":
                    case "zip":
                            $ctype = "application/zip";
                            break;
                    case "doc":
                            $ctype = "application/msword";
                            break;
                    case "xls":
                            $ctype = "application/vnd.ms-excel";
                            break;
                    case "ppt":
                            $ctype = "application/vnd.ms-powerpoint";
                            break;
                    case "gif":
                            $ctype = "image/gif";
                            break;
                    case "png":
                            $ctype = "image/png";
                            break;
                    case "jpeg":
                    case "jpg":
                            $ctype = "image/jpeg";
                            break;
                    case "wav":
                            $ctype = "audio/x-wav";
                            break;
                    case "mpeg":
                    case "mpg":
                    case "mpe":
                            $ctype = "video/x-mpeg";
                            break;
                    case "mov":
                            $ctype = "video/quicktime";
                            break;
                    case "avi":
                            $ctype = "video/x-msvideo";
                            break;
                    case "txt":
                            $ctype = "text/plain";
                            break;
                    default:
                            $ctype = "application/octet-stream";
            }
            ob_end_clean();
            header('Last-Modified: ' . gmdate('D, d M Y H:i:s', $timestamp + 86400) . ' GMT');
            header('Expires: ' . gmdate('D, d M Y H:i:s', $timestamp + 86400) . ' GMT');
            header('Cache-control: max-age=86400');
            header('Content-Encoding: none');
            header("Content-Disposition: $attachment; filename=\"{$attach['name']}\"");
            header("Content-type: $ctype");
            header("Content-Transfer-Encoding: binary");
            $filesize && header("Content-Length: $filesize");
            $i = 1;
            while (!@readfile($fgeturl)) {
                    if (++$i > 3) break;
            }
            exit();
    }

    public function deleteAction() {

            $aid = $this->getInput('aid', 'post');
            if (!$aid) {
                    $this->showError('operate.fail');
            }
            if (!$attach = Wekit::load('attach.PwThreadAttach')->getAttach($aid)) {
                    $this->showError('data.error');
            }

            Wind::import('SRV:forum.bo.PwForumBo');
            $forum = new PwForumBo($attach['fid']);
            if (!$forum->isForum()) {
                    $this->showError('data.error');
            }

            if ($this->loginUser->uid != $attach['created_userid']) {
                    if (!$this->loginUser->getPermission('operate_thread.deleteatt', $forum->isBM($this->loginUser->username))) {
                            $this->showError('permission.attach.delete.deny');
                    }
                    if (!$this->loginUser->comparePermission($attach['created_userid'])) {
                            $this->showError(array('permission.level.deleteatt', array('{grouptitle}' => $this->loginUser->getGroupInfo('name'))));
                    }
            }

            Wekit::load('attach.PwThreadAttach')->deleteAttach($aid);
            Pw::deleteAttach($attach['path'], $attach['ifthumb']);
            if ($this->loginUser->uid != $attach['created_userid']) {
                    Wekit::load('log.srv.PwLogService')->addDeleteAtachLog($this->loginUser, $attach);
            }

            if ($attach['tid']) {
                    if (!$attach['pid']) {
                            $thread = Wekit::load('forum.PwThread')->getThread($attach['tid'], PwThread::FETCH_ALL);
                            Wind::import('SRV:forum.dm.PwTopicDm');
                            $dm = new PwTopicDm($attach['tid']);
                            if (!Wekit::load('attach.PwThreadAttach')->countType($attach['tid'], 0, $attach['type'])) {
                                    $dm->setHasAttach($attach['type'], false);
                            }
                            if (!Pw::getstatus($thread['tpcstatus'], PwThread::STATUS_OPERATORLOG) && $this->loginUser->uid != $attach['created_userid']) {
                                    $dm->setOperatorLog(true);
                            }
                    } else {
                            $thread = Wekit::load('forum.PwThread')->getPost($attach['pid']);
                            Wind::import('SRV:forum.dm.PwReplyDm');
                            $dm = new PwReplyDm($attach['pid']);
                    }
                    if ($thread['aids'] > 0) {
                            $thread['aids']--;
                    }
                    $dm->setAids($thread['aids']);
                    if (($content = str_replace('[attachment=' . $aid . ']', '', $thread['content'])) != $thread['content']) {
                            $dm->setContent($content);
                    }
                    if (!$attach['pid']) {
                            Wekit::load('forum.PwThread')->updateThread($dm);
                    } else {
                            Wekit::load('forum.PwThread')->updatePost($dm);
                    }
            }

            $this->showMessage('success');
    }

    public function recordAction() {
            list($aid, $page) = $this->getInput(array('aid', 'page'));
            $perpage = 10;
            $page < 1 && $page = 1;

            list($offset, $limit) = Pw::page2limit($page, $perpage);
            $count = Wekit::load('attach.PwThreadAttachBuy')->countByAid($aid);
            if (!$count) {
                    $this->showError('BBS:thread.buy.error.norecord');
            }
            Wind::import('SRV:credit.bo.PwCreditBo');
            $record = Wekit::load('attach.PwThreadAttachBuy')->getByAid($aid, $limit, $offset);
            !$record && $this->showError('BBS:thread.buy.error.norecord');	
            $users = Wekit::load('user.PwUser')->fetchUserByUid(array_keys($record));

            $data = array();
            $cType = PwCreditBo::getInstance()->cType;
            foreach ($record as $key => $value) {
                    $data[] = array(
                            'uid' => $value['created_userid'],
                            'username' => $users[$value['created_userid']]['username'],
                            'cost' => $value['cost'],
                            'ctype' => $cType[$value['ctype']],
                            'created_time' => Pw::time2str($value['created_time'])
                    );
            }

            $totalpage = ceil($count / $perpage);
            $nextpage = $page+1;
            $nextpage = $nextpage > $totalpage ? $totalpage : $nextpage;

            $this->setOutput(array('data' => $data, 'totalpage' => $totalpage, 'page' => $nextpage), 'data');
            $this->showMessage('success');
    }

    private function _getDownloadCredit($operation, PwUserBo $user, PwCreditBo $creditBo, $creditset = array()) {
            $strategy = $creditBo->getStrategy($operation);
            if ($this->_checkCreditSetEmpty($strategy['credit']) && $this->_checkCreditSetEmpty($creditset['credit'])) {
                    return false;
            }

            //如果外部有积分设置传入则使用外部的积分设置策略
            if (!empty($creditset['limit']) || ($creditset['credit'] && false === $this->_checkCreditSetEmpty($creditset['credit']))) {
                    $strategy['limit'] = $creditset['limit'];
                    $strategy['credit'] = $creditset['credit'];
            }
            if ($strategy['limit']) {
                    $count = $creditBo->getOperateCount($user->uid, $operation);
                    if ($count >= $strategy['limit']) return false;
            }
            return $strategy['credit'];
    }

    private function _checkCreditSetEmpty($credit) {
            foreach ($credit as $key => $value) {
                    if ($value) return false;
            }
            return true;
    }

    /**
     * 检查购买积分
     */
    protected function _checkAttachCost($attach) {
            if (!$attach['cost']) return $attach;
            $user = $this->loginUser;
            if ($attach['created_userid'] == $user->uid) {
                    $attach['cost'] = 0;
                    return $attach;
            }
            $attachbuy = Wekit::load('attach.PwThreadAttachBuy');
            if (!$attachbuy->getByAidAndUid($attach['aid'], $user->uid)) {
                    $myCredit = $user->getCredit($attach['ctype']);
                    if ($attach['cost'] > $myCredit) {
                            Wind::import('SRV:credit.bo.PwCreditBo');
                            $creditBo = PwCreditBo::getInstance();
                            $creditType = $creditBo->cType[$attach['ctype']];
                            return new PwError('BBS:thread.buy.error.credit.notenough', array('{myCredit}' => $myCredit.$creditType, '{count}' => -$attach['cost'].$creditType));
                    } 
            } else {
                    $attach['cost'] = 0;
            }
            return $attach;
    }

    /**
     * 下载购买积分
     */
    protected function _checkAttachDownload($operate, $attach, PwForumBo $forum) {
            $user = $this->loginUser;
            if (1 != $user->getPermission('allow_download')) {
                    return false;
            }
            Wind::import('SRV:credit.bo.PwCreditBo');
            $creditBo = PwCreditBo::getInstance();
            $forumCredit = $forum->getCreditSet($operate);
            $downloadCredit = $this->_getDownloadCredit($operate, $user, $creditBo, $forumCredit);
            if (!$downloadCredit) return false; 
            if (!$user->isExists()) {
                    return new PwError('download.fail.login.not');
            }
            $attachdownload = Wekit::load('attach.PwThreadAttachDownload');
            $ifDown = $attachdownload->getByAidAndUid($attach['aid'], $user->uid);
            if ($ifDown) return false;
            $reduceDownload = '';
            foreach ($downloadCredit as $k => $v) {
                    $tv = $v;
                    ($attach['ctype'] == $k) && $tv = $v - $attach['cost'];
                    $vt = $tv > 0 ? '+'.$tv : $tv;
                    if (-$tv > $user->getCredit($k)) {
                            return new PwError('BBS:thread.download.error.credit.notenough', array('{myCredit}' => $this->loginUser->getCredit($k).$creditBo->cType[$k], '{count}' => $vt.$creditBo->cType[$k]));
                    } 
                    $v && $reduceDownload .= ($v > 0 ? '+'.abs($v) : $v).$creditBo->cType[$k].',';
            }
            return $reduceDownload;
    }

    /**
     * 更新积分
     */
    protected function _operateCredit($operate, PwForumBo $forum) {
            Wind::import('SRV:credit.bo.PwCreditBo');
            $credit = PwCreditBo::getInstance();
            $user = $this->loginUser;
            $credit->operate($operate, $user, true, array('forumname' => $forum->foruminfo['name']),$forum->getCreditSet($operate));
            $credit->execute();
    }

    protected function _operateBuyCredit($attach) {
            $user = $this->loginUser;
            if (!$attach['cost'] || $attach['created_userid'] == $user->uid) {
                    return false;
            }
            Wind::import('SRV:credit.bo.PwCreditBo');
            $creditBo = PwCreditBo::getInstance();
            Wind::import('SRV:attach.dm.PwThreadAttachBuyDm');
            $dm = new PwThreadAttachBuyDm();
            $dm->setAid($attach['aid'])
                    ->setCreatedUserid($user->uid)
                    ->setCreatedTime(Pw::getTime())
                    ->setCtype($attach['ctype'])
                    ->setCost($attach['cost']);
            Wekit::load('attach.PwThreadAttachBuy')->add($dm);

            $creditBo->addLog('attach_buy', array($attach['ctype'] => -$attach['cost']), $user, array(
                    'name' => $attach['name']
            ));
            $creditBo->set($user->uid, $attach['ctype'], -$attach['cost'], true);

            $user = new PwUserBo($attach['created_userid']);
            if (($max = $user->getPermission('sell_credit_range.maxincome')) && Wekit::load('attach.PwThreadAttachBuy')->sumCost($attach['aid']) > $max) {

            } else {
                    $creditBo->addLog('attach_sell', array($attach['ctype'] => $attach['cost']), $user, array(
                            'name' => $attach['name']
                    ));
                    $creditBo->set($user->uid, $attach['ctype'], $attach['cost'], true);
            }
            $creditBo->execute();
    }
    

}
