ArticleService.class.php 11.2 KB
<?php
/**
 * Created by PhpStorm.
 * User: liyifei2012it
 * Date: 17/4/12
 * Time: 10:46
 */
namespace Common\Service;

use Com\Rpc;
use Common\Common\Constant;
use Common\Common\NewsHelper;
use Common\Model\ArticleModel;
use Common\Model\ClassModel;
use VcySDK\Cron;
use VcySDK\Service;

class ArticleService extends AbstractService
{

    // 新闻二维码地址
    const NEWS_QRCODE_URL = 'News/Frontend/NewsQrcode';

    // 构造方法
    public function __construct()
    {
        parent::__construct();
        $this->_d = new ArticleModel();
        $this->_class = new ClassModel();
    }

    /**
     * 格式化数据
     * @author liyifei
     * @param array $article 新闻数据
     * @param array $attachs 附件数据数组
     * @return array
     */
    public function formatData($article, $attachs = null)
    {
        // unset多余数据
        $unsetParam = [
            'ea_id',
            'ea_name',
            'top_time',
            'update_time',
            'unread_total',
            'domain',
            'status',
            'created',
            'updated',
            'deleted',
        ];

        foreach ($article as $k => $v) {
            if (in_array($k, $unsetParam)) {
                unset($article[$k]);
            }
        }

        $article['parent_id'] = 0;
        $article['parent_name'] = '';

        // 返回父分类ID,方便前端定位
        $class = $this->_class->get($article['class_id']);

        if ($class) {
            $parent_class = $this->_class->get($class['parent_id']);

            if ($parent_class) {
                $article['parent_id'] = $parent_class['class_id'];
                $article['parent_name'] = $parent_class['class_name'];
            }
        }

        // 反序列化积分策略数据
        if (!empty($article['strategys'])) {
            $formatStrategys = [];
            $strategys = unserialize($article['strategys']);
            foreach ($strategys as $action_key => $strategy_id) {
                $formatStrategys[] = [
                    'action_key' => $action_key,
                    'strategy_id' => $strategy_id,
                ];
            }
            $article['strategys'] = $formatStrategys;
        }

        // 反序列化学分策略数据
        if (!empty($article['credit_strategys'])) {
            $formatStrategys = [];
            $strategys = unserialize($article['credit_strategys']);
            foreach ($strategys as $action_key => $strategy_id) {
                $formatStrategys[] = [
                    'action_key' => $action_key,
                    'strategy_id' => $strategy_id,
                ];
            }
            $article['credit_strategys'] = $formatStrategys;
        }

        // 新闻内容格式化,图文混排标签转换
        if (!empty($article['content']) && is_array($attachs) && !empty($attachs)) {
            $attach_list = [];

            foreach ($attachs as $list) {
                foreach ($list as $k => $v) {
                    $attach_list[$k] = $v;
                }
            }

            $pattern = '/<img[^<]*(news_video|news_audio)="(\w+)".*\/>/iU';
            $matches = [];
            preg_match_all($pattern, $article['content'], $matches, PREG_SET_ORDER);

            foreach ($matches as $matche) {
                // $matche[0] = 将要被替换的字符串
                // $matche[1] = news_video 或 news_audio
                // $matche[2] = 附件ID
                if (count($matche) != 3 || !isset($attach_list[$matche[2]])) {
                    continue;
                }

                $attach = $attach_list[$matche[2]];
                $html = '';

                switch ($matche[1]) {
                    // 视频
                    case 'news_video':
                        $html = "<{$matche[1]} at_url=\"{$attach['at_convert_url']}\" cover=\"{$attach['at_cover_url']}\" />";
                        break;
                    // 音频
                    case 'news_audio':
                        $html = "<{$matche[1]} at_name=\"{$attach['at_name']}\" at_time=\"{$attach['at_time']}\" at_url=\"{$attach['at_url']}\" />";
                        break;
                }

                $article['content'] = str_replace($matche[0], $html, $article['content']);
            }
        }

        return $article;
    }

    /**
     * @desc 新增新闻推荐
     * @author tangxingguo
     * @param int $articleId 新闻ID
     * @param array $postRight 用户提交的权限数据
     * @return mixed
     */
    public function addNewsRpc($articleId, $postRight)
    {

        // 预发布与草稿不推送
        $articleInfo = $this->get($articleId);
        if (in_array($articleInfo['news_status'], [Constant::NEWS_STATUS_DRAFT, Constant::NEWS_STATUS_READY_SEND, Constant::NEWS_STATUS_TIMING_RELEASE])) {
            return false;
        }

        // 权限数据
        $newsHelper = &NewsHelper::instance();
        $articleInfo['right'] = $newsHelper->formatRightForRPC($postRight);

        // 格式化RPC参数
        $param_arr = $this->formatRpcParams($articleInfo, 1);

        // 推送
        $url = rpcUrl('/Public/Rpc/Recommender/ArticleNew');
        $res = Rpc::phprpc($url)->invoke('Index', $param_arr);

        return $res;
    }

    /**
     * @desc 更新新闻推荐
     * @author tangxingguo
     * @param Int $articleId 新闻ID
     * @param array $articleInfo 新闻信息
     * @param array $postRight 用户提交的权限数据
     * @return mixed
     */
    public function updateNewsRpc($articleId, $articleInfo, $postRight)
    {
        // 预发布与草稿不推送
        if (in_array($articleInfo['news_status'], [Constant::NEWS_STATUS_DRAFT, Constant::NEWS_STATUS_READY_SEND])) {
            return false;
        }
        $info = $this->get($articleId);
        if (empty($info)) {
            return false;
        }
        $articleInfo['article_id'] = $articleId;

        // 权限数据
        $newsHelper = &NewsHelper::instance();
        $articleInfo['right'] = $newsHelper->formatRightForRPC($postRight);

        // 格式化RPC参数
        $param_arr = $this->formatRpcParams($articleInfo, 1);

        // 推送
        $url = rpcUrl('/Public/Rpc/Recommender/ArticleUpdate');
        $res = Rpc::phprpc($url)->invoke('Index', $param_arr);

        return $res;
    }

    /**
     * @desc 删除新闻推荐
     * @author tangxingguo
     * @param int $articleId 新闻ID
     * @return mixed
     */
    public function delNewsRpc($articleId)
    {
        $articleInfo = $this->get($articleId);

        // 格式化RPC参数
        $param_arr = $this->formatRpcParams($articleInfo, 2);

        // 推送
        $url = rpcUrl('/Public/Rpc/Recommender/ArticleDelete');
        $res = Rpc::phprpc($url)->invoke('Index', $param_arr);

        return $res;
    }

    /**
     * @desc 格式化RPC数据
     * @author tangxingguo
     * @param array $articleInfo 新闻信息
     * @param int $paramType 数据类型(1=添加、更新;2=删除)
     * @return array RPC参数
     */
    private function formatRpcParams($articleInfo, $paramType)
    {
        $param_arr = [];
        switch ($paramType) {
            // 更新或添加
            case 1:
                $param_arr = [
                    // 被推荐数据所在应用模块目录标识名
                    'app'=>'News',
                    // 被推荐数据所属的分类Id,可以为空,但必须提供该参数
                    'dataCategoryId' => $articleInfo['class_id'],
                    // 被推荐数据的原始数据 Id
                    'dataId' => $articleInfo['article_id'],
                    // 文章标题
                    'title' => $articleInfo['title'],
                    // 文章摘要
                    'summary' => $articleInfo['summary'],
                    // 封面图片附件 ID
                    'attachId' => $articleInfo['cover_id'],
                    // 封面图片 url
                    'pic' => $articleInfo['cover_url'],
                    // 文章链接
                    'url' => 'News/Frontend/Index/Detail/Index?article_id=' . $articleInfo['article_id'],
                    // 文章发布时间戳,不设置或者为空,则以推荐时间为准
                    'dateline' => $articleInfo['send_time'],
                    // 文章阅读权限范围,为空则表示全部人员,否则需要构造数组
                    'right' => $articleInfo['right'],
                ];
                break;
            // 删除
            case 2:
                $param_arr = [
                    // 被推荐数据所在应用模块目录标识名
                    'app'=>'News',
                    // 被推荐数据所属的分类Id,可以为空,但必须提供该参数
                    'dataCategoryId' => $articleInfo['class_id'],
                    // 被推荐数据的原始数据 Id
                    'dataId' => $articleInfo['article_id'],
                ];
                break;
        }

        return $param_arr;
    }

    /**
     * 创建数据标识
     * @author zhonglei
     * @return string
     */
    public function buildDataID()
    {
        $data_id = md5(sprintf('%s_%s_%s', QY_DOMAIN, APP_DIR, MILLI_TIME));
        $count = $this->count_by_conds(['data_id' => $data_id]);

        if ($count == 0) {
            return $data_id;
        }

        return $this->buildDataID();
    }

    /**
     * 根据动作Key获取策略ID
     * @author zhonglei
     * @param array $article 新闻数据
     * @param string $action_key 动作Key
     * @return string
     */
    public function getStrategyID($article, $action_key)
    {
        $strategy_id = '';

        if (!is_array($article) || empty($article)) {
            return $strategy_id;
        }

        // 非自定义策略
        if ($article['strategy_setting'] != Constant::NEWS_STRATEGY_CUSTOM) {
            return $strategy_id;
        }

        // 反序列化
        if (!is_array($article['strategys'])) {
            $article['strategys'] = empty($article['strategys']) ? [] : unserialize($article['strategys']);
        }

        // 根据动作Key获取策略ID
        if (isset($article['strategys'][$action_key])) {
            $strategy_id = $article['strategys'][$action_key];
        }

        return $strategy_id;
    }

    /**
     * 增加定时任务
     * @param int $id 新闻ID
     * @param int $cronTime 执行时间
     * @return bool
     */
    public function cronAdd($id, $cronTime)
    {
        // 实例化定时任务类
        $cron_serv = new Cron(Service::instance());

        // 参数
        $conds_remind = [
            'crRemark' => 'news_cron',
            'crType' => 2,
            'crParams' => json_encode(['article_id' => $id]),
            'crMethod' => 'POST',
            'crReqUrl' => oaUrl('Frontend/Callback/Release/Index'), // 回调地址
            'crTimes' => 1,
            'crCron' => rgmdate((String)$cronTime, 's i G j n ? Y'),
            'crMonitorExecution' => 0,
            'crDescription' => '头条定时发布'
        ];

        // 创建定时任务
        $res_publish = $cron_serv->add($conds_remind);
        $cron_publish = $res_publish['crId'];

        $this->update($id, ['release_crid' => $cron_publish]);

        return true;
    }
}