<?php
/*
 * @Author: TaoLer <alipey_tao@qq.com>
 * @Date: 2022-04-13 09:54:31
 * @LastEditTime: 2022-04-21 11:39:38
 * @LastEditors: TaoLer
 * @Description: 搜索引擎SEO优化设置
 * @FilePath: \TaoLer\app\admin\controller\Seo.php
 * Copyright (c) 2020~2022 http://www.aieok.com All rights reserved.
 */
declare(strict_types=1); 
namespace app\admin\controller;

use app\common\controller\AdminController;
use think\facade\View;
use think\facade\Request;
use think\facade\Db;
use taoser\SetArr;
use app\admin\model\PushJscode;

class Seo extends AdminController
{

    public function index()
    {
        // 站点地图
        $xml = '';
        $xmlArr = $this->getXmlFile(public_path());
        foreach($xmlArr as $v) {
            $map =  $this->getIndexUrl().'/'.$v;
            $xml .= $map."\n";                  
        }
        // robots
        if(is_file($rob = public_path().'robots.txt')){
            $robots = file_get_contents($rob);
        } else {
            $robots = '';
        }     
        // push_js
        $pushjs = new PushJscode();
        $jscode = $pushjs->getAllCodes();
        View::assign(['xml'=>$xml,'jscode'=>$jscode,'robots'=>$robots]);
        return View::fetch();
    }

    public function push()
    {
        $data = Request::only(['start_id','end_id']);

        if(empty(config('taoler.baidu.push_api'))) return json(['code'=>-1,'msg'=>'请先配置接口push_api']);
        $urls = [];
        if(empty($data['start_id']) || empty($data['end_id'])) {
            $artAllId = Db::name('article')->where(['delete_time'=>0,'status'=>1])->column('id');
        } else {
            $artAllId = Db::name('article')->where(['delete_time'=>0,'status'=>1])->where('id','between',[$data['start_id'],$data['end_id']])->column('id');
        }

        foreach($artAllId as $aid) {
            $urls[] = $this->getRouteUrl($aid);
        }
        $api = config('taoler.baidu.push_api');
        $ch = curl_init();
        $options =  array(
            CURLOPT_URL => $api,
            CURLOPT_POST => true,
            CURLOPT_RETURNTRANSFER => true,
            CURLOPT_POSTFIELDS => implode("\n", $urls),
            CURLOPT_HTTPHEADER => array('Content-Type: text/plain'),
        );
        curl_setopt_array($ch, $options);
        $result = curl_exec($ch);
        if($result == false) {
            return json(['code'=>-1,'msg'=>'接口失败']);
        }
        $res = stripos($result,'error');
        $data = json_decode($result); 
        if($res !== false) {    
            return json(['code'=>-1,'msg'=>$data->message]);
        };   
        return json(['code'=>0,'msg'=>'成功推送'.$data->success.'条,今天剩余'.$data->remain]);
    }

    /**
     * 百度接口配置
     *
     * @return void
     */
    public function config()
    {
        $baidu = [];
        $data = Request::only(['client_id','client_secret','push_api']);
        foreach($data as $k => $v) {
            if($v !== ''){
                if($k == 'push_api') {
                    $baidu[$k] = "'$v'";
                } else {
                    $baidu[$k] = $v;
                }
            }
        }
        $res = SetArr::name('taoler')->edit([
            'baidu' => $baidu,
        ]);
        if($res == true){
            return json(['code'=>0,'msg'=>'设置成功']);
        }
    }

    /**
     * 百度谷歌sitemap生成xml文件
     *
     * @return void
     */
    public function map()
    {
        $data = Request::only(['map_num','map_time','map_level']);
        // 写文件字符串
        $str = '';
        // 标记第一次调用写ID
        $flag= true;
        // 写ID
        $w_id = '';
        // 新文件编号
        $i = 1;
        // 获取public下所有xml文件
        $newFile = $this->getXmlFile(public_path());
        // 没有xml文件时,不存在重写
        if(empty($newFile)) {
            $rewrite = false;
        } else {
            $xmlFile = end($newFile);
            $strFile = file_get_contents(public_path().$xmlFile);
            $num = substr_count($strFile, '<url>');
            // 是否有需要追加在文件,判断最新文件是否未写满
            $rewrite = $num < $data['map_num'] ? true : false;
        }
        
       if($rewrite){
            // 需要追加的数量
           $limit = (int) $data['map_num'] - $num;
           $name = pathinfo($xmlFile,PATHINFO_FILENAME);
           $arr = explode('_', $name);
           // 检验当天,避免重复生成
           if($arr[0] == date('Y-d-m'))
           {
               $i = $arr[1] + 1;
           }
       } else {
            $limit = (int) $data['map_num'];
       }
        // 最新ID
        $maxId = Db::name('article')->where(['delete_time'=>0,'status'=>1])->max('id');

        do
        {
            $wr_id = $flag ? config('taoler.sitemap.write_id') : $w_id;
            $artAllId = Db::name('article')
                        ->where(['delete_time'=>0,'status'=>1])
                        ->where('id', '>', (int) $wr_id)
                        ->order('id','asc')->limit($limit)->column('update_time','id');
            if(empty($artAllId)) {
                return json(['code'=>-1,'msg'=>'本次无需生成']);
            } else {
                // 本次最新文件ID
                $last_id = array_key_last($artAllId);
                // 循环拼接文件字符串
                foreach($artAllId as $aid => $uptime) {
                    // url生成
                    $url = $this->getRouteUrl($aid);
                    $time = date('Y-m-d', $uptime);
                    // 组装字符串
                    $str .= <<<STR
                    <url>
                        <loc>$url</loc>
                        <lastmod>$time</lastmod>
                        <changefreq>daily</changefreq>
                        <priority>0.5</priority>
                    </url>\n
                    STR;         
                }
                
                // 写文件
                if($rewrite){
                    // 写入旧xml文件
                    $reps = $str.'</urlset>';
                    $xml = preg_replace('/<\/urlset>/', $reps, $strFile);
                    $res = file_put_contents(public_path().$xmlFile, $xml);
                    if($res == false){
                        return json(['code'=>-1,'msg'=>$xmlFile.'写入失败']);
                    }
                    $limit = $data['map_num'];
                    $rewrite = false;
                } else {
                    // 生成新xml
                    $xml = <<<XML
                    <?xml version="1.0" encoding="utf-8"?>	<!-- XML文件需以utf-8编码-->
                    <urlset>\n$str</urlset>
                    XML;              
                    $res = file_put_contents(public_path().date('Y-m-d').'_'.$i.'.xml', $xml);
                    if($res == false){
                        return json(['code'=>-1,'msg'=>date('Y-m-d').'_'.$i.'.xml写入失败']);
                    }
                }
                // 重置标记内容
                $str = '';
                $i++;
                $w_id = $last_id;
                $flag = false;
            }
        }
        while($last_id < (int) $maxId);
        // 写配置,标记最后写入ID
        $res = SetArr::name('taoler')->edit([
            'sitemap' => [
                'map_num'	=> $data['map_num'],
                'write_id'	=> $last_id,
            ],
        ]);
        if($res == false){
            return json(['code'=>-1,'msg'=>'写xml配置失败']);
        }
        
        return json(['code'=>0,'msg'=>'生成xml成功']);
    }

    /**
     * 返回public目录下xml名称数组
     *
     * @param string $dir
     * @return array
     */
    public function getXmlFile(string $dir) : array
    {
        $arr = [];
        $files = array_diff(scandir($dir), array('.', '..'));
        foreach ($files as $file) {
            if(is_file("$dir/$file") && !is_link($dir) && (pathinfo("$dir/$file", PATHINFO_EXTENSION)) == 'xml') 
            {
                $arr[] =  "$file";
            }
        }
        return $arr;
    }
    
    /**
     * 生成robots
     *
     * @return void
     */
    public function robots()
    {
        if(Request::isPost()){
            $txt = input('robots');
            $xmlArr = $this->getXmlFile(public_path());
            foreach($xmlArr as $v) {
                $res = stripos($txt, $v);
                if($res == false){
                    $map =  $this->getIndexUrl().'/'.$v;
                    $txt .= "\nsitemap:".$map;                   
                }
            }
            $res = file_put_contents(public_path().'robots.txt',$txt);
            if($res == false){
                return json(['code'=>-1,'msg'=>$v.'写入失败']);
            }
            return json(['code'=>0,'msg'=>'设置成功']);
        }
    }

    /**
     * 保存搜索平台js代码
     *
     * @return void
     */
    public function savePushJs()
    {
        $data = Request::only(['name','jscode']);
        if(empty($data['name'])) {
            return json(['code'=>-1,'msg'=>'请术输入名称']);
        }
        if(empty($data['jscode'])){
            return json(['code'=>-1,'msg'=>'请术输入代码']);
        }
        $push = new PushJscode();
        $res = $push->saveCode($data);
        if(!$res) {
            return json(['code'=>-1,'msg'=>'保存失败']);
        }
        return json(['code'=>0,'msg'=>'保存成功']);
    }

    /**
     * 删除平台js代码
     *
     * @return void
     */
    public function delPushJs()
    {
        $id = (int) input('id');
        $push = new PushJscode();
        $res = $push->delCode($id);
        if(!$res) {
            return json(['code'=>-1,'msg'=>'删除失败']);
        }
        return json(['code'=>0,'msg'=>'删除成功']);
    }

}